Python 在执行if后保持上下文管理器打开。。。else语句
我有以下方案,带有不同的条件Python 在执行if后保持上下文管理器打开。。。else语句,python,if-statement,with-statement,contextmanager,Python,If Statement,With Statement,Contextmanager,我有以下方案,带有不同的条件和语句: if not remote: _open = open os.chdir(localpath) else: sftp = pysftp.Connection(host, username=user, password=sftppwd) with sftp: sftp.chdir(remotepath) _open = sftp.open with _open('myfile', 'rb') a
和语句:
if not remote:
_open = open
os.chdir(localpath)
else:
sftp = pysftp.Connection(host, username=user, password=sftppwd)
with sftp:
sftp.chdir(remotepath)
_open = sftp.open
with _open('myfile', 'rb') as f: # and then lots of other files are opened too
x = f.read(4)
...
最后一行在remote
情况下失败,因为sftp
对象/上下文管理器已过期
我读过,但这里不完全一样:我可以为非远程案例创建一个虚拟上下文管理器,但我不确定这是否足够
我曾考虑过使用ExitStack
,但我担心在打开更多文件时会显得很复杂:每个简单的都需要将_open(…)作为f:
重写为可读性较差的堆栈。当更多代码到达时,请输入_context(_open(…)
在这种情况下,最简单的解决方案是什么?(尽可能避免创建新函数,并保持简单的if…else流程)您的代码的主要功能是希望您的具有_open():…
上下文管理器位于远程分支的另一个上下文管理器内,在另一种情况下可以自由漫游。
我认为最简单的方法是使用虚拟上下文管理器,这里将对其进行更深入的讨论:
简单地说,您可以在非远程情况下设置虚拟上下文管理器,例如:
import os
# from contextlib import suppress as nullcontext # Python 3.4+
from contextlib import nullcontext # Python 3.7+
import pysftp
remote = False
localpath = '.'
remotepath = '.'
if not remote:
_open_cm = nullcontext()
_open_cm.chdir = os.chdir
_open_cm.open = open
_path = localpath
else:
_open_cm = pysftp.Connection(host, username=user, password=sftppwd)
_path = remotepath
with _open_cm:
_open_cm.chdir(_path)
with _open_cm.open('myfile', 'rb') as f:
x = f.read(4)
...
(警告!我没有测试上面的代码,它使用了猴子补丁,但只是为了让您了解这一点)我不明白您为什么不将pysftp.Connection(…)作为sftp:
。否则,您是否考虑过创建一个包装器对象来执行所有必要的设置过程,并返回需要用作上下文管理器的对象?上下文管理器正在完成它的工作:一旦您退出范围,就关闭连接。唯一的解决方法是不要将与
一起使用,但最后你必须记住自己关闭连接。这可能也不坏。为什么没有新功能?我相信只要加上一个就可以很容易地解决这个问题function@sal如果我记得一次与。。。也会在出现异常时进行处理,以便无论如何都能很好地完成事情。所以我想保留它,避免自己靠近它。如何@DaniMesejo?如果你指的是一个新函数中的最后两行,那么不是(因为它实际上比这更复杂)。