Gardez le gestionnaire de contexte ouvert après une instruction if… else [duplicate]
J'ai le schéma suivant, avec différentes with
instructions conditionnelles :
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)
...
La dernière ligne échoue dans le remote
cas car le sftp
gestionnaire d'objets / contextes a expiré.
J'ai lu Conditionnel avec instruction en Python , mais ici ce n'est pas exactement la même chose: je pourrais créer un gestionnaire de contexte factice pour le cas non distant, mais je ne suis pas sûr que ce serait suffisant.
J'ai pensé à utiliser, ExitStack
mais j'ai peur que cela semble complexe lors de l'ouverture de fichiers supplémentaires: chaque simple with _open(...) as f:
devrait être réécrit dans un stack.enter_context(_open(...))
code moins lisible lorsque du code supplémentaire arrive.
Quelle est la solution la plus simple dans ce cas? (en évitant de créer de nouvelles fonctions si possible et en gardant un flux if ... else simple)
Réponses
La caractéristique principale de votre code est que vous voulez que votre with _open(): ...
gestionnaire de contexte soit à l'intérieur d'un autre gestionnaire de contexte pour la branche distante et qu'il soit librement itinérant dans l'autre cas. Je pense que le plus simple est d'utiliser un gestionnaire de contexte factice, qui est discuté plus en détail ici: Comment écrire un gestionnaire de contexte nul (sans opération) en Python?
En bref, vous mettriez en place un gestionnaire de contexte factice dans le cas non distant, par exemple:
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)
...
(ATTENTION! Je n'ai pas testé le code ci-dessus, et il utilise le monkey-patching , mais juste pour vous avoir l'idée)