Lassen Sie den Kontextmanager nach einer if… else-Anweisung [duplizieren] geöffnet.
Ich habe das folgende Schema mit verschiedenen bedingten with
Anweisungen:
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)
...
Die letzte Zeile schlägt in diesem remote
Fall fehl , weil der sftp
Objekt- / Kontextmanager abgelaufen ist.
Ich habe Conditional with-Anweisung in Python gelesen , aber hier ist es nicht genau dasselbe: Ich könnte einen Dummy-Kontextmanager für den nicht entfernten Fall erstellen, bin mir aber nicht sicher, ob dies ausreichen würde.
Ich habe überlegt, es zu verwenden, ExitStack
aber dann befürchte ich, dass es beim Öffnen weiterer Dateien komplex aussehen würde: Jede einfache Datei with _open(...) as f:
müsste in eine weniger lesbare Datei umgeschrieben werden, stack.enter_context(_open(...))
wenn mehr Code eintrifft.
Was ist in diesem Fall die einfachste Lösung? (Vermeiden Sie nach Möglichkeit das Erstellen neuer Funktionen und halten Sie einen einfachen if ... else-Fluss aufrecht.)
Antworten
Das Hauptmerkmal Ihres Codes ist, dass Sie möchten, dass sich Ihr with _open(): ...
Kontextmanager in einem anderen Kontextmanager für den Remote- Zweig befindet und im anderen Fall frei Roaming ist. Ich denke, am einfachsten ist es, einen Dummy-Kontextmanager zu verwenden, auf den hier näher eingegangen wird: Wie schreibe ich einen Null-Kontextmanager (no-op) in Python?
Kurz gesagt, Sie würden im nicht entfernten Fall einen Dummy-Kontextmanager einrichten, z.
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)
...
(WARNUNG! Ich habe den obigen Code nicht getestet und er verwendet Affen-Patches , aber nur, um Ihnen die Idee zu vermitteln.)