@@ -399,6 +399,8 @@ The execution of the :keyword:`with` statement with one "item" proceeds as follo
399
399
#. The context expression (the expression given in the :token: `with_item `) is
400
400
evaluated to obtain a context manager.
401
401
402
+ #. The context manager's :meth: `__enter__ ` is loaded for later use.
403
+
402
404
#. The context manager's :meth: `__exit__ ` is loaded for later use.
403
405
404
406
#. The context manager's :meth: `__enter__ ` method is invoked.
@@ -430,17 +432,41 @@ The execution of the :keyword:`with` statement with one "item" proceeds as follo
430
432
value from :meth: `__exit__ ` is ignored, and execution proceeds at the normal
431
433
location for the kind of exit that was taken.
432
434
435
+ The following code::
436
+
437
+ with EXPRESSION as TARGET:
438
+ SUITE
439
+
440
+ is semantically equivalent to::
441
+
442
+ manager = (EXPRESSION)
443
+ enter = type(manager).__enter__
444
+ exit = type(manager).__exit__
445
+ value = enter(manager)
446
+ hit_except = False
447
+
448
+ try:
449
+ TARGET = value
450
+ SUITE
451
+ except:
452
+ hit_except = True
453
+ if not exit(manager, *sys.exc_info()):
454
+ raise
455
+ finally:
456
+ if not hit_except:
457
+ exit(manager, None, None, None)
458
+
433
459
With more than one item, the context managers are processed as if multiple
434
460
:keyword: `with ` statements were nested::
435
461
436
462
with A() as a, B() as b:
437
- suite
463
+ SUITE
438
464
439
- is equivalent to ::
465
+ is semantically equivalent to::
440
466
441
467
with A() as a:
442
468
with B() as b:
443
- suite
469
+ SUITE
444
470
445
471
.. versionchanged :: 3.1
446
472
Support for multiple context expressions.
@@ -772,24 +798,25 @@ iterators.
772
798
The following code::
773
799
774
800
async for TARGET in ITER:
775
- BLOCK
801
+ SUITE
776
802
else:
777
- BLOCK2
803
+ SUITE2
778
804
779
805
Is semantically equivalent to::
780
806
781
807
iter = (ITER)
782
808
iter = type(iter).__aiter__(iter)
783
809
running = True
810
+
784
811
while running:
785
812
try:
786
813
TARGET = await type(iter).__anext__(iter)
787
814
except StopAsyncIteration:
788
815
running = False
789
816
else:
790
- BLOCK
817
+ SUITE
791
818
else:
792
- BLOCK2
819
+ SUITE2
793
820
794
821
See also :meth: `__aiter__ ` and :meth: `__anext__ ` for details.
795
822
@@ -811,23 +838,27 @@ able to suspend execution in its *enter* and *exit* methods.
811
838
812
839
The following code::
813
840
814
- async with EXPR as VAR :
815
- BLOCK
841
+ async with EXPRESSION as TARGET :
842
+ SUITE
816
843
817
- Is semantically equivalent to::
844
+ is semantically equivalent to::
818
845
819
- mgr = (EXPR)
820
- aexit = type(mgr).__aexit__
821
- aenter = type(mgr).__aenter__(mgr)
846
+ manager = (EXPRESSION)
847
+ aexit = type(manager).__aexit__
848
+ aenter = type(manager).__aenter__
849
+ value = await aenter(manager)
850
+ hit_except = False
822
851
823
- VAR = await aenter
824
852
try:
825
- BLOCK
853
+ TARGET = value
854
+ SUITE
826
855
except:
827
- if not await aexit(mgr, *sys.exc_info()):
856
+ hit_except = True
857
+ if not await aexit(manager, *sys.exc_info()):
828
858
raise
829
- else:
830
- await aexit(mgr, None, None, None)
859
+ finally:
860
+ if not hit_except:
861
+ await aexit(manager, None, None, None)
831
862
832
863
See also :meth: `__aenter__ ` and :meth: `__aexit__ ` for details.
833
864
0 commit comments