Last active
October 13, 2016 13:22
-
-
Save CMCDragonkai/04b9064f005b8ebe704e7addbcc20973 to your computer and use it in GitHub Desktop.
Python: Run Code that Prints to STDOUT or STDERR and Capture the Output into a Variable (a.k.a. output buffering to a variable)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# derived from https://wrongsideofmemphis.wordpress.com/2010/03/01/store-standard-output-on-a-variable-in-python/ | |
import sys | |
from io import StringIO | |
# from StringIO import StringIO # for python2 | |
# These functions are not thread-safe and are not thread-local, it is global | |
# across the entire process (all subthreads). It does not apply to child | |
# processes. If during the execution of `func`, the current thread yields to | |
# another thread, then you may experience both a leak of the global side-effect | |
# and/or race conditions on the mutation of the stdout/stderr designators. | |
# Oh just discovered `contextlib.redirect_stdout` and `contextlib.redirect_stderr` | |
# They are available on the latest Python 3. They do the same thing, but are also | |
# re-entrant. | |
# This means, you can reuse the same context multiple times. However these | |
# functions should also be re-entrant, but each nested call will print to a new | |
# buffer. There's no way to reuse the same buffer. | |
# The contextlib is more flexible, as you get to choose whether you want to | |
# reuse the same buffer, or start a new buffer! Plus it's in the standard | |
# library! | |
def capture_out(func): | |
try: | |
old_stdout = sys.stdout | |
result = StringIO() | |
sys.stdout = result | |
func() | |
result_string = result.getvalue() | |
return result_string | |
finally: | |
sys.stdout = old_stdout | |
def capture_err(func): | |
try: | |
old_stderr = sys.stderr | |
result = StringIO() | |
sys.stderr = result | |
func() | |
result_string = result.getvalue() | |
return result_string | |
finally: | |
sys.stderr = old_stderr | |
def capture_out_err(func): | |
try: | |
old_stdout = sys.stdout | |
old_stderr = sys.stderr | |
result_out = StringIO() | |
result_err = StringIO() | |
sys.stdout = result_out | |
sys.stderr = result_err | |
func() | |
result_out_string = result_out.getvalue() | |
result_err_string = result_out.getvalue() | |
return (result_out_string, result_err_string) | |
finally: | |
sys.stdout = old_stdout | |
sys.stderr = old_stderr | |
def capture_out_err_inter(func): | |
try: | |
old_stdout = sys.stdout | |
old_stderr = sys.stderr | |
result = StringIO() | |
sys.stdout = result | |
sys.stderr = result | |
func() | |
result_string = result.getvalue() | |
return result_string | |
finally: | |
sys.stdout = old_stdout | |
sys.stderr = old_stderr |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment