@@ -129,16 +129,16 @@ Functions and classes provided:
129
129
Context managers defined with :func: `asynccontextmanager ` can be used
130
130
either as decorators or with :keyword: `async with ` statements::
131
131
132
- import time
133
- from contextlib import asynccontextmanager
132
+ import time
133
+ from contextlib import asynccontextmanager
134
134
135
- @asynccontextmanager
136
- async def timeit():
137
- now = time.monotonic()
138
- try:
139
- yield
140
- finally:
141
- print(f'it took {time.monotonic() - now}s to run')
135
+ @asynccontextmanager
136
+ async def timeit():
137
+ now = time.monotonic()
138
+ try:
139
+ yield
140
+ finally:
141
+ print(f'it took {time.monotonic() - now}s to run')
142
142
143
143
@timeit()
144
144
async def main():
@@ -149,9 +149,9 @@ Functions and classes provided:
149
149
created by :func: `asynccontextmanager ` to meet the requirement that context
150
150
managers support multiple invocations in order to be used as decorators.
151
151
152
- .. versionchanged :: 3.10
153
- Async context managers created with :func: `asynccontextmanager ` can
154
- be used as decorators.
152
+ .. versionchanged :: 3.10
153
+ Async context managers created with :func: `asynccontextmanager ` can
154
+ be used as decorators.
155
155
156
156
157
157
.. function :: closing(thing)
@@ -248,16 +248,16 @@ Functions and classes provided:
248
248
It can also be used as a stand-in for
249
249
:ref: `asynchronous context managers <async-context-managers >`::
250
250
251
- async def send_http(session=None):
252
- if not session:
253
- # If no http session, create it with aiohttp
254
- cm = aiohttp.ClientSession()
255
- else:
256
- # Caller is responsible for closing the session
257
- cm = nullcontext(session)
251
+ async def send_http(session=None):
252
+ if not session:
253
+ # If no http session, create it with aiohttp
254
+ cm = aiohttp.ClientSession()
255
+ else:
256
+ # Caller is responsible for closing the session
257
+ cm = nullcontext(session)
258
258
259
- async with cm as session:
260
- # Send http requests with session
259
+ async with cm as session:
260
+ # Send http requests with session
261
261
262
262
.. versionadded :: 3.7
263
263
@@ -280,25 +280,25 @@ Functions and classes provided:
280
280
281
281
For example::
282
282
283
- from contextlib import suppress
283
+ from contextlib import suppress
284
284
285
- with suppress(FileNotFoundError):
286
- os.remove('somefile.tmp')
285
+ with suppress(FileNotFoundError):
286
+ os.remove('somefile.tmp')
287
287
288
- with suppress(FileNotFoundError):
289
- os.remove('someotherfile.tmp')
288
+ with suppress(FileNotFoundError):
289
+ os.remove('someotherfile.tmp')
290
290
291
291
This code is equivalent to::
292
292
293
- try:
294
- os.remove('somefile.tmp')
295
- except FileNotFoundError:
296
- pass
293
+ try:
294
+ os.remove('somefile.tmp')
295
+ except FileNotFoundError:
296
+ pass
297
297
298
- try:
299
- os.remove('someotherfile.tmp')
300
- except FileNotFoundError:
301
- pass
298
+ try:
299
+ os.remove('someotherfile.tmp')
300
+ except FileNotFoundError:
301
+ pass
302
302
303
303
This context manager is :ref: `reentrant <reentrant-cms >`.
304
304
@@ -319,21 +319,21 @@ Functions and classes provided:
319
319
``__enter__ `` method and so is available as the target of the
320
320
:keyword: `with ` statement::
321
321
322
- with redirect_stdout(io.StringIO()) as f:
323
- help(pow)
324
- s = f.getvalue()
322
+ with redirect_stdout(io.StringIO()) as f:
323
+ help(pow)
324
+ s = f.getvalue()
325
325
326
326
To send the output of :func: `help ` to a file on disk, redirect the output
327
327
to a regular file::
328
328
329
- with open('help.txt', 'w') as f:
330
- with redirect_stdout(f):
331
- help(pow)
329
+ with open('help.txt', 'w') as f:
330
+ with redirect_stdout(f):
331
+ help(pow)
332
332
333
333
To send the output of :func: `help ` to *sys.stderr *::
334
334
335
- with redirect_stdout(sys.stderr):
336
- help(pow)
335
+ with redirect_stdout(sys.stderr):
336
+ help(pow)
337
337
338
338
Note that the global side effect on :data: `sys.stdout ` means that this
339
339
context manager is not suitable for use in library code and most threaded
@@ -656,13 +656,13 @@ may come from the number of context managers needed being driven by user
656
656
input (such as opening a user specified collection of files), or from
657
657
some of the context managers being optional::
658
658
659
- with ExitStack() as stack:
660
- for resource in resources:
661
- stack.enter_context(resource)
662
- if need_special_resource():
663
- special = acquire_special_resource()
664
- stack.callback(release_special_resource, special)
665
- # Perform operations that use the acquired resources
659
+ with ExitStack() as stack:
660
+ for resource in resources:
661
+ stack.enter_context(resource)
662
+ if need_special_resource():
663
+ special = acquire_special_resource()
664
+ stack.callback(release_special_resource, special)
665
+ # Perform operations that use the acquired resources
666
666
667
667
As shown, :class: `ExitStack ` also makes it quite easy to use :keyword: `with `
668
668
statements to manage arbitrary resources that don't natively support the
@@ -828,33 +828,33 @@ writing both a function decorator and a context manager for the task,
828
828
inheriting from :class: `ContextDecorator ` provides both capabilities in a
829
829
single definition::
830
830
831
- from contextlib import ContextDecorator
832
- import logging
831
+ from contextlib import ContextDecorator
832
+ import logging
833
833
834
- logging.basicConfig(level=logging.INFO)
834
+ logging.basicConfig(level=logging.INFO)
835
835
836
- class track_entry_and_exit(ContextDecorator):
837
- def __init__(self, name):
838
- self.name = name
836
+ class track_entry_and_exit(ContextDecorator):
837
+ def __init__(self, name):
838
+ self.name = name
839
839
840
- def __enter__(self):
841
- logging.info('Entering: %s', self.name)
840
+ def __enter__(self):
841
+ logging.info('Entering: %s', self.name)
842
842
843
- def __exit__(self, exc_type, exc, exc_tb):
844
- logging.info('Exiting: %s', self.name)
843
+ def __exit__(self, exc_type, exc, exc_tb):
844
+ logging.info('Exiting: %s', self.name)
845
845
846
846
Instances of this class can be used as both a context manager::
847
847
848
- with track_entry_and_exit('widget loader'):
849
- print('Some time consuming activity goes here')
850
- load_widget()
848
+ with track_entry_and_exit('widget loader'):
849
+ print('Some time consuming activity goes here')
850
+ load_widget()
851
851
852
852
And also as a function decorator::
853
853
854
- @track_entry_and_exit('widget loader')
855
- def activity():
856
- print('Some time consuming activity goes here')
857
- load_widget()
854
+ @track_entry_and_exit('widget loader')
855
+ def activity():
856
+ print('Some time consuming activity goes here')
857
+ load_widget()
858
858
859
859
Note that there is one additional limitation when using context managers
860
860
as function decorators: there's no way to access the return value of
@@ -890,25 +890,25 @@ Context managers created using :func:`contextmanager` are also single use
890
890
context managers, and will complain about the underlying generator failing
891
891
to yield if an attempt is made to use them a second time::
892
892
893
- >>> from contextlib import contextmanager
894
- >>> @contextmanager
895
- ... def singleuse():
896
- ... print("Before")
897
- ... yield
898
- ... print("After")
899
- ...
900
- >>> cm = singleuse()
901
- >>> with cm:
902
- ... pass
903
- ...
904
- Before
905
- After
906
- >>> with cm:
907
- ... pass
908
- ...
909
- Traceback (most recent call last):
910
- ...
911
- RuntimeError: generator didn't yield
893
+ >>> from contextlib import contextmanager
894
+ >>> @contextmanager
895
+ ... def singleuse():
896
+ ... print("Before")
897
+ ... yield
898
+ ... print("After")
899
+ ...
900
+ >>> cm = singleuse()
901
+ >>> with cm:
902
+ ... pass
903
+ ...
904
+ Before
905
+ After
906
+ >>> with cm:
907
+ ... pass
908
+ ...
909
+ Traceback (most recent call last):
910
+ ...
911
+ RuntimeError: generator didn't yield
912
912
913
913
914
914
.. _reentrant-cms :
@@ -925,20 +925,20 @@ using the same context manager.
925
925
:func: `suppress `, :func: `redirect_stdout `, and :func: `chdir `. Here's a very
926
926
simple example of reentrant use::
927
927
928
- >>> from contextlib import redirect_stdout
929
- >>> from io import StringIO
930
- >>> stream = StringIO()
931
- >>> write_to_stream = redirect_stdout(stream)
932
- >>> with write_to_stream:
933
- ... print("This is written to the stream rather than stdout")
934
- ... with write_to_stream:
935
- ... print("This is also written to the stream")
936
- ...
937
- >>> print("This is written directly to stdout")
938
- This is written directly to stdout
939
- >>> print(stream.getvalue())
940
- This is written to the stream rather than stdout
941
- This is also written to the stream
928
+ >>> from contextlib import redirect_stdout
929
+ >>> from io import StringIO
930
+ >>> stream = StringIO()
931
+ >>> write_to_stream = redirect_stdout(stream)
932
+ >>> with write_to_stream:
933
+ ... print("This is written to the stream rather than stdout")
934
+ ... with write_to_stream:
935
+ ... print("This is also written to the stream")
936
+ ...
937
+ >>> print("This is written directly to stdout")
938
+ This is written directly to stdout
939
+ >>> print(stream.getvalue())
940
+ This is written to the stream rather than stdout
941
+ This is also written to the stream
942
942
943
943
Real world examples of reentrancy are more likely to involve multiple
944
944
functions calling each other and hence be far more complicated than this
@@ -971,31 +971,31 @@ Another example of a reusable, but not reentrant, context manager is
971
971
when leaving any with statement, regardless of where those callbacks
972
972
were added::
973
973
974
- >>> from contextlib import ExitStack
975
- >>> stack = ExitStack()
976
- >>> with stack:
977
- ... stack.callback(print, "Callback: from first context")
978
- ... print("Leaving first context")
979
- ...
980
- Leaving first context
981
- Callback: from first context
982
- >>> with stack:
983
- ... stack.callback(print, "Callback: from second context")
984
- ... print("Leaving second context")
985
- ...
986
- Leaving second context
987
- Callback: from second context
988
- >>> with stack:
989
- ... stack.callback(print, "Callback: from outer context")
990
- ... with stack:
991
- ... stack.callback(print, "Callback: from inner context")
992
- ... print("Leaving inner context")
993
- ... print("Leaving outer context")
994
- ...
995
- Leaving inner context
996
- Callback: from inner context
997
- Callback: from outer context
998
- Leaving outer context
974
+ >>> from contextlib import ExitStack
975
+ >>> stack = ExitStack()
976
+ >>> with stack:
977
+ ... stack.callback(print, "Callback: from first context")
978
+ ... print("Leaving first context")
979
+ ...
980
+ Leaving first context
981
+ Callback: from first context
982
+ >>> with stack:
983
+ ... stack.callback(print, "Callback: from second context")
984
+ ... print("Leaving second context")
985
+ ...
986
+ Leaving second context
987
+ Callback: from second context
988
+ >>> with stack:
989
+ ... stack.callback(print, "Callback: from outer context")
990
+ ... with stack:
991
+ ... stack.callback(print, "Callback: from inner context")
992
+ ... print("Leaving inner context")
993
+ ... print("Leaving outer context")
994
+ ...
995
+ Leaving inner context
996
+ Callback: from inner context
997
+ Callback: from outer context
998
+ Leaving outer context
999
999
1000
1000
As the output from the example shows, reusing a single stack object across
1001
1001
multiple with statements works correctly, but attempting to nest them
@@ -1005,15 +1005,15 @@ statement, which is unlikely to be desirable behaviour.
1005
1005
Using separate :class: `ExitStack ` instances instead of reusing a single
1006
1006
instance avoids that problem::
1007
1007
1008
- >>> from contextlib import ExitStack
1009
- >>> with ExitStack() as outer_stack:
1010
- ... outer_stack.callback(print, "Callback: from outer context")
1011
- ... with ExitStack() as inner_stack:
1012
- ... inner_stack.callback(print, "Callback: from inner context")
1013
- ... print("Leaving inner context")
1014
- ... print("Leaving outer context")
1015
- ...
1016
- Leaving inner context
1017
- Callback: from inner context
1018
- Leaving outer context
1019
- Callback: from outer context
1008
+ >>> from contextlib import ExitStack
1009
+ >>> with ExitStack() as outer_stack:
1010
+ ... outer_stack.callback(print, "Callback: from outer context")
1011
+ ... with ExitStack() as inner_stack:
1012
+ ... inner_stack.callback(print, "Callback: from inner context")
1013
+ ... print("Leaving inner context")
1014
+ ... print("Leaving outer context")
1015
+ ...
1016
+ Leaving inner context
1017
+ Callback: from inner context
1018
+ Leaving outer context
1019
+ Callback: from outer context
0 commit comments