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?如果你指的是一个新函数中的最后两行,那么不是(因为它实际上比这更复杂)。