Introduction to Monkey Patching
By Trey Hunner
Monkey patching: modifying or extending code at runtime
Let's walk through some examples.
Capturing Standard Output
What if we want the print statement to be captured to a variable or file instead of printing to the screen? Can we do that?
Let's try replacing
sys.stdout so print doesn't output to the screen.
>>> import sys >>> from StringIO import StringIO >>> >>> real_stdout = sys.stdout >>> sys.stdout = StringIO() >>> >>> print "hello" >>> print "where is this output going?" >>> >>> real_stdout.write(sys.stdout.getvalue()) hello where is this output going? >>> >>> sys.stdout = real_stdout >>> >>> print "is this printing out?" is this printing out? >>> print "yes it is!" yes it is!
What if we replace
sys.stdout with something that's not a file-like object?
>>> import sys >>> sys.stdout = None >>> print "hello!" Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'NoneType' object has no attribute 'write'
Let's make a context manager to capture standard output and save it to a file!
>>> from iopatch import print_to_file >>> >>> with print_to_file('test.txt'): ... print "hello!" ... >>> with open('test.txt') as f: ... print f.read() hello! >>>
You can check out the implementation in the
Mock is a cool tool that can help you monkey patch things.
When writing a test for our
day_of_week function, we probably want to make sure it always returns the correct date in a variety of situations (not just for today's date).
Let's force the
today method on the
date class in our
utils module to return June 22, 2014 all the time.
>>> from mock import patch >>> from datetime import date >>> >>> from utils import day_of_week >>> >>> with patch('utils.date') as fake_date: ... fake_date.today.return_value = date(2014, 6, 22) ... print day_of_week() # Should print Sunday ... Sunday >>> print day_of_week() # Should print today's day of week Thursday
Changing code at runtime may be dangerous. Monkey patching can sometimes help a lot while testing, but use it in production code only with extreme caution.
To the extent possible under law, the author has dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty.
You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.