Python 101: Redirecting stdout
We deal with output redirection all the time. Review how to do it in Python here.
Join the DZone community and get the full member experience.
Join For Freeredirecting stdout is something most developers will need to do at some point or other. it can be useful to redirect stdout to a file or to a file-like object. i have also redirected stdout to a text control in some of my desktop gui projects. in this article, we will look at the following:
- redirecting stdout to a file (simple)
- the shell redirection method
- redirecting stdout using a custom context manager
- python 3’s contextlib.redirect_stdout()
- redirect stdout to a wxpython text control
redirecting stdout
the easiest way to redirect stdout in python is to just assign it an open file object. let’s take a look at a simple example:
import sys
def redirect_to_file(text):
original = sys.stdout
sys.stdout = open('/path/to/redirect.txt', 'w')
print('this is your redirected text:')
print(text)
sys.stdout = original
print('this string goes to stdout, not the file!')
if __name__ == '__main__':redirecting stdout / stderr
redirect_to_file('python rocks!')
here we just import python’s sys module and create a function that we can pass strings that we want to have redirected to a file. we save off a reference to
sys.stdout
so we can restore it at the end of the function. this can be useful if you intend to use stdout for other things. before you run this code, be sure to update the path to something that will work on your system. when you run it, you should see the following in your file:
this is your redirected text:
python rocks!
that last print statement will go to stdout, not the file.
shell redirection
shell redirection is also pretty common, especially in linux, although windows also works the same way in most cases. let’s create a silly example of a noisy function that we will call noisy.py:
# noisy.py
def noisy(text):
print('the noisy function prints a lot')
print('here is the string you passed in:')
print('*' * 40)
print(text)
print('*' * 40)
print('thank you for calling me!')
if __name__ == '__main__':
noisy('this is a test of python!')
you will notice that we didn’t import the sys module this time around. the reason is that we don’t need it since we will be using shell redirection. to do shell redirection, open a terminal (or command prompt) and navigate to the folder where you saved the code above. then execute the following command:
python noisy.py > redirected.txt
the greater than character (i.e. >) tells your operating system to redirect stdout to the filename you specified. at this point, you should have a file named “redirected.txt” in the same folder as your python script. if you open it up, the file should have the following contents:
the noisy function prints a lot
here is the string you passed in:
****************************************
this is a test of python!
****************************************
thank you for calling me!
now wasn’t that pretty cool?
redirect stdout with a context manager
another fun way to redirect stdout is by using a context manager. let’s create a custom context manager that accepts a file object to redirect stdout to:
import sys
from contextlib import contextmanager
@contextmanager
def custom_redirection(fileobj):
old = sys.stdout
sys.stdout = fileobj
try:
yield fileobj
finally:
sys.stdout = old
if __name__ == '__main__':
with open('/path/to/custom_redir.txt', 'w') as out:
with custom_redirection(out):
print('this text is redirected to file')
print('so is this string')
print('this text is printed to stdout')
when you run this code, it will write out two lines of text to your file and one to stdout. as usual, we reset stdout at the end of the function.
using contextlib.redirect_stdout
python 3.4 added the redirect_stdout function to their contextlib module. let’s try using that to create a context manager to redirect stdout:
import sys
from contextlib import redirect_stdout
def redirected(text, path):
with open(path, 'w') as out:
with redirect_stdout(out):
print('here is the string you passed in:')
print('*' * 40)
print(text)
print('*' * 40)
if __name__ == '__main__':
path = '/path/to/red.txt'
text = 'my test to redirect'
redirected(text, path)
this code is a little simpler because the built-in function does all the yielding and resetting of stdout automatically for you. otherwise, it works in pretty much the same way as our custom context manager.
redirecting stdout in wxpython
i have written about redirecting stdout in wxpython on several occasions. the following code is actually from an article i wrote in 2009 and updated in 2015:
import sys
import wx
class myform(wx.frame):
def __init__(self):
wx.frame.__init__(self, none,
title="wxpython redirect tutorial")
# add a panel so it looks the correct on all platforms
panel = wx.panel(self, wx.id_any)
style = wx.te_multiline|wx.te_readonly|wx.hscroll
log = wx.textctrl(panel, wx.id_any, size=(300,100),
style=style)
btn = wx.button(panel, wx.id_any, 'push me!')
self.bind(wx.evt_button, self.onbutton, btn)
# add widgets to a sizer
sizer = wx.boxsizer(wx.vertical)
sizer.add(log, 1, wx.all|wx.expand, 5)
sizer.add(btn, 0, wx.all|wx.center, 5)
panel.setsizer(sizer)
# redirect text here
sys.stdout = log
def onbutton(self, event):
print "you pressed the button!"
# run the program
if __name__ == "__main__":
app = wx.app(false)
frame = myform().show()
app.mainloop()
this code just creates a simple frame with a panel that contains a multi-line text control and a button. whenever you press the button, it will print out some text to stdout, which we have redirected to the text control. give it a try to see how well it works!
wrapping up
now you know several different methods for redirecting stdout to files. some methods are better than others. personally, i thought it was cool that python 3 now has a context manager built in just for this purpose. speaking of which, python 3 also has a function for redirecting stderr. all of these examples can be modified slightly to support redirecting stderr or both stdout and stderr. the very last thing we touched on was redirecting stdout to a text control in wxpython. this can be really useful for debugging or for grabbing the output from a subprocess, although in the latter case you will need to print out the output to have it redirected correctly.
Published at DZone with permission of Mike Driscoll, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments