On 22 August 2017 at 15:34, Nick Coghlan <ncogh...@gmail.com> wrote: > On 21 August 2017 at 11:32, Neil Girdhar <mistersh...@gmail.com> wrote: >> This question describes an example of the problem: >> https://stackoverflow.com/questions/8416208/in-python-is-there-a-good-idiom-for-using-context-managers-in-setup-teardown. >> You want to invoke a context manager in your setup/tearing-down, but the >> easiest way to do that is to override run, which seems ugly. > > Using context managers when you can't use a with statement is one of > the main use cases for contextlib.ExitStack(): > > def setUp(self): > self._resource_stack = stack = contextlib.ExitStack() > self._resource = stack.enter_context(MyResource()) > > def tearDown(self): > self._resource_stack.close() > > I posted that as an additional answer to the question: > https://stackoverflow.com/questions/8416208/in-python-is-there-a-good-idiom-for-using-context-managers-in-setup-teardown/45809502#45809502
Sjoerd pointed out off-list that this doesn't cover the case where you're acquiring multiple resources and one of the later acquisitions fails, so I added the ExitStack idiom that covers that case (using stack.pop_all() as the last operation in a with statement): def setUp(self): with contextlib.ExitStack() as stack: self._resource1 = stack.enter_context(GetResource()) self._resource2 = stack.enter_context(GetOtherResource()) # Failures before here -> immediate cleanup self.addCleanup(stack.pop_all().close) # Now cleanup won't happen until the cleanup functions run I also remember that using addCleanup lets you avoid defining tearDown entirely. Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/