是否可以在退出 block 之前重新分配 with block 的对象?
具体用例
我与 FTP 服务器交互,偶尔会在传输过程中断开连接,而 IT 部门不愿意对此采取任何措施。作为我自己工具的解决方法,我使用了一个包装器,它会在放弃之前重试传输几次:
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
这个包装器工作正常,但似乎不能在 with
block 中使用,就像可以使用普通的 FTP 连接一样。如果 except
子句被命中,连接将重新建立,但是在退出 with
block 时,python 将尝试关闭原始的 conn
,不是新的:
with ftplib.FTP(**kwargs) as conn:
conn = retry(conn, **kwargs)
这可以用自定义上下文管理器来演示,显示 python 从原始对象调用 __exit__()
,即使变量在 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>
如何在 with
block 中重新分配 conn
以便 python 在最新的对象上调用 __exit__()
方法,而不是原来的?这样的事情甚至是可能的,还是我被迫没有 with
block 并且必须记住在任何地方调用 conn.quit()
?
如果重要的话,我想要一些与 python 2 和 3 都兼容的东西。如果一个解决方案与两者都不兼容,那么我更喜欢 python 3 特定的解决方案而不是 python 2 特定的解决方案
最佳答案
回答您的一般性问题,不,您不能,如 PEP 343 所示“规范:with 语句”。您上下文中的变量 e
被保存到一个内部变量中,该变量在拆卸时使用。
对于具体的FTP连接,其他答案中已经提出了一些其他选项。
关于python - 在 with block 中重新分配变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36558280/