Reputation: 461
The code below with with
statement runs successfully.
class A(object):
def __enter__(self):
return self
def __exit__(self, et, ev, tb):
print 1
a = A()
class B(object):
def __enter__(self):
return self
__exit__ = a.__exit__
b = B()
# ok here, without any error
with b:
print 2
However, if we translate with
statement into the code based on pep343, there will be an error.
import sys
mgr = b
exit = type(mgr).__exit__
value = type(mgr).__enter__(mgr)
exc = True
try:
try:
print 1
except:
exc = False
if not exit(mgr, *sys.exc_info()):
raise
finally:
if exc:
exit(mgr, None, None, None)
Because type(b).__exit__(a, None, None, None)
equals A.__exit__(a, a, None, None, None)
, the error is caused by too many parameters.
My question is
with
statement in python different from pep343with
statement or context manager in pythonUpvotes: 0
Views: 84
Reputation: 251041
The reason you're getting this error is that you're assigning an instance method from A
to B
's __exit__
, this results in too many arguments because you're passing the instance again with exit
: exit(mgr, None, None, None)
, and it being a bound method, it will append the instance again resulting in too many arguments.
Hence, you can get rid of mgr
argument from the exit
calls.
Based on your code:
In [21]: B.__exit__.__self__
Out[21]: <__main__.A at 0x110bb65d0>
In [22]: A.__exit__.__self__
Out[22]: None
Upvotes: 1