<p>如果您担心<code>setup</code>中引发的异常导致<code>teardown</code>方法无法调用,那么可以使用<a href="https://docs.python.org/3/library/contextlib.html" rel="nofollow">^{<cd4>}</a>中的<a href="https://docs.python.org/3/library/contextlib.html#contextlib.ExitStack" rel="nofollow">^{<cd3>}</a>类。如果<code>ExitStack</code>中出现异常,<code>setup</code>可以确保管理器类正确关闭。你知道吗</p>
<pre><code>from io import StringIO
from contextlib import ExitStack
managers = []
close_managers = None
def setup():
global close_managers
with ExitStack() as exit_stack:
managers[:] = [exit_stack.enter_context(StringIO()) for _ in range(2)]
# any exception raised before this line will will cause all the __exit__
# methods of the given context managers to be called. So this should
# be the last part of setup
close_managers = exit_stack.pop_all().close
def teardown():
m1, m2 = managers
assert m1.getvalue() == 'test1 m1\ntest2 m1\n'
assert m2.getvalue() == 'test1 m2\ntest2 m2\n'
close_managers()
def test1():
m1, m2 = managers
m1.write('test1 m1\n')
m2.write('test1 m2\n')
def test2():
m1, m2 = managers
m1.write('test2 m1\n')
m2.write('test2 m2\n')
</code></pre>