Skip to content

Instantly share code, notes, and snippets.

@cjerdonek
Created November 1, 2014 16:28
Show Gist options
  • Save cjerdonek/34a2b255a2fca01d3bae to your computer and use it in GitHub Desktop.
Save cjerdonek/34a2b255a2fca01d3bae to your computer and use it in GitHub Desktop.
A Python 3.4 module to illustrate a difference between exception handling in generators and context managers.
"""
This module illustrates a difference in exception handling between
generator functions and context managers.
This script should be run with **Python 3.4.2** or higher (which is what
it was originally run with).
To witness what is illustrated in this module, run the following two
commands from the command-line.
1) Generator example
In this example, notice that the generator does *not* handle the
ValueError, despite its try-except.
$ python -c "import test_yield; test_yield.test_gen()"
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/Users/chris_g4/Dev/elections/open-rcv/test_yield.py", line 13, in test_gen
raise ValueError("val")
ValueError: val
2) Context manager example
In this example, notice that the context manager *does* handle
the ValueError.
$ python -c "import test_yield; test_yield.test_manager()"
Traceback (most recent call last):
File "/Users/chris_g4/Dev/elections/open-rcv/test_yield.py", line 19, in manager
yield 1
File "/Users/chris_g4/Dev/elections/open-rcv/test_yield.py", line 24, in test_manager
raise ValueError("val")
ValueError: val
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/Users/chris_g4/Dev/elections/open-rcv/test_yield.py", line 24, in test_manager
raise ValueError("val")
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/contextlib.py", line 77, in __exit__
self.gen.throw(type, value, traceback)
File "/Users/chris_g4/Dev/elections/open-rcv/test_yield.py", line 21, in manager
raise TypeError("foo")
TypeError: foo
"""
from contextlib import contextmanager
def test_gen():
def gen():
try:
yield 1
except ValueError:
raise TypeError("foo")
for value in gen():
# The generator does not handle this error despite the try-except.
raise ValueError("val")
def test_manager():
@contextmanager
def manager():
try:
yield 1
except ValueError:
raise TypeError("foo")
with manager():
# For the context manager, the error is handled.
raise ValueError("val")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment