Is it possible to reassign the object of a with-block prior to exiting the block?
I interact with an FTP server that occasionally drops connections mid-transfer, and IT is not willing to do anything about it. As a workaround for my own tools, I'm using a wrapper that will retry transfers a few times before giving up:
def retry(conn, max_tries=3, **kwargs):
this_try = 1
while (this_try <= max_tries):
try:
# upload / download / whatever
return conn
except ftplib.all_errors:
conn.quit()
time.sleep(60)
conn = ftplib.FTP(**kwargs)
this_try += 1
This wrapper works fine, but doesn't doesn't appear to be usable inside a with
block, like normal FTP connections can be used. If the except
clause is ever hit, the connection will be re-established, but on exiting the with
block, python will attempt to close the original conn
, not the new one:
with ftplib.FTP(**kwargs) as conn:
conn = retry(conn, **kwargs)
This can be demonstrated with a custom context manager, showing that python calls __exit__()
from the original object, even if the variable is reassigned mid-block:
>>> class Echo(object):
... def __enter__(self):
... print('entering ' + repr(self))
... return self
... def __exit__(self, *args):
... print('exiting ' + repr(self))
...
>>> with Echo() as e:
... e = Echo()
...
entering <__main__.Echo object at 0x026C14F0>
exiting <__main__.Echo object at 0x026C14F0>
>>> e
<__main__.Echo object at 0x026C1410>
How can I reassign conn
inside the with
block so that python calls the __exit__()
method on the latest object, instead of the original one? Is such a thing even possible, or am I forced to go without with
blocks and have to remember to call conn.quit()
everywhere?
If it matters, I'd like something compatible with both python 2 and 3. If a solution is not compatible with both, then I would prefer a python 3-specific solution over a python 2-specific solution
Answering your general question, no you cannot, as shown in PEP 343 "Specification: The with statement". The variable e
in your context is saved into an internal variable which is used at tear-down time.
For the specific FTP connection, some other options have been proposed in the other answers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With