¿Usar un administrador de contexto para la salida del script de Python a un archivo?

Estoy progtwigndo un script en el que tengo una opción, que se pasa en la línea de comandos, ya sea que el script deba imprimir sus resultados en stdout o en un archivo de resultados predefinido. Un esquema de código para esto se muestra a continuación. Ahora he leído un poco sobre los administradores de contexto en Python, pero no estoy realmente seguro de cómo usar un administrador de contexto en esta situación específica. Así que estoy buscando consejo

  1. Si tiene sentido usar un administrador de contexto en este problema
  2. cómo ir implementándolo.

Entonces, el código sin administrador de contexto es:

option_file = True # would come from OptionParser in real code if option_file: out = open("resultsfile", "w") else: out = sys.stdout # do some computations out.write("Results of script") # more computations and calls to out.write if option_file: out.close() 

Un administrador de contexto es algo que puede usar con una sentencia with . Está explícitamente diseñado para:

  • realizar alguna configuración,
  • darte un objeto, y
  • realice de nuevo un desassembly (incluso si lanza una excepción).

Por ejemplo, open se puede utilizar como un administrador de contexto. En el siguiente código

 with open(...) as f: # do stuff 

No importa lo que sea, el archivo siempre estará cerrado. (Bueno, generalmente. Excepto en casos tontos como el apagado de energía o el proceso de eliminación).

Debe utilizar un administrador de contexto cuando se encuentre en este tipo de situación. No me parece que seas, por lo que no veo ninguna razón para un administrador de contexto.


Existe una forma alternativa (no mejor o peor, solo diferente) de escribir su código que utiliza un administrador de contexto. Si desea redireccionar stdout temporalmente, pero asegúrese de restaurarlo cuando haya terminado, entonces se encuentra en la situación anterior. Aquí hay un ejemplo:

 @contextlib.contextmanager def redirect_stdout(stream): import sys sys.stdout = stream yield sys.stdout = sys.__stdout__ 

A continuación, puede escribir código como

 with open(...) as f: with redirect_stdout(f): # do stuff 

y cualquier escritura a stdout en stuff irá a f lugar.


EDITAR: Tiene razón en que no hay forma condicional de tener un administrador de contexto: o está en uno o no. Siempre puedes escribir el tuyo, lo que no puede hacer nada:

 @contextlib.contextmanager def maybe_open(path, do_nothing=True): if do_nothing: f = None yield sys.stdout else: f = open(path) yield f if f: f.close() 

Esto es casi seguro que es una exageración.