在 if ... else 语句之后保持上下文管理器打开
Keep context manager open after an if ... else statement
我有以下方案,具有不同的条件 with
语句:
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
但我担心打开更多文件时看起来会很复杂:每个简单的 with _open(...) as f:
都需要重写为可读性较差的 stack.enter_context(_open(...))
当更多代码到达时。
在这种情况下最简单的解决方案是什么?(尽可能避免创建新函数并保持简单的 if ... else 流程)
代码的主要特点是您希望 with _open(): ...
上下文管理器位于 remote 分支的另一个上下文管理器中,并在其他情况。
我认为最简单的方法是使用虚拟上下文管理器,这里有更深入的讨论:
简而言之,您可以在非远程情况下设置虚拟上下文管理器,例如:
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)
...
(警告!我没有测试过上面的代码,它使用了 monkey-patching,但只是为了让你明白)
我有以下方案,具有不同的条件 with
语句:
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
但我担心打开更多文件时看起来会很复杂:每个简单的 with _open(...) as f:
都需要重写为可读性较差的 stack.enter_context(_open(...))
当更多代码到达时。
在这种情况下最简单的解决方案是什么?(尽可能避免创建新函数并保持简单的 if ... else 流程)
代码的主要特点是您希望 with _open(): ...
上下文管理器位于 remote 分支的另一个上下文管理器中,并在其他情况。
我认为最简单的方法是使用虚拟上下文管理器,这里有更深入的讨论:
简而言之,您可以在非远程情况下设置虚拟上下文管理器,例如:
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)
...
(警告!我没有测试过上面的代码,它使用了 monkey-patching,但只是为了让你明白)