¿Cómo duplicar sys.stdout en un archivo de registro?

Editar: Ya que parece que no hay solución, o estoy haciendo algo tan poco estándar que nadie lo sabe, revisaré mi pregunta para preguntar también: ¿Cuál es la mejor manera de lograr el registro cuando una aplicación de Python está haciendo muchas llamadas al sistema

Mi aplicación tiene dos m, odas. En modo interactivo, quiero que toda la salida vaya a la pantalla, así como a un archivo de registro, incluida la salida de cualquier llamada del sistema. En el modo demonio, toda la salida va al registro. El modo Daemon funciona muy bien usandoos.dup2(). No puedo encontrar una manera de "conectar" todas las salidas a un registro en modo interactivo, sin modificar todas y cada una de las llamadas al sistema.

n otras palabras, quiero la funcionalidad de la línea de comando 'tee' para cualquier salida generada por una aplicación python,incluyendo la salida de llamada del sistema.

Para aclarar

Para redirigir toda la salida, hago algo como esto, y funciona muy bien:

# open our log file
so = se = open("%s.log" % self.name, 'w', 0)

# re-open stdout without buffering
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

# redirect stdout and stderr to the log file opened above
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())

Lo bueno de esto es que no requiere llamadas de impresión especiales del resto del código. El código también ejecuta algunos comandos de shell, por lo que es bueno no tener que lidiar con cada uno de sus resultados individualmente también.

Simplemente, quiero hacer lo mismo, excepto duplicando en lugar de redirigir.

n un primer momento, pensé que simplemente revertir eldup2as @ deberían funcionar. ¿Por qué no lo hace? Aquí está mi prueba:

import os, sys

### my broken solution:
so = se = open("a.log", 'w', 0)
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

os.dup2(sys.stdout.fileno(), so.fileno())
os.dup2(sys.stderr.fileno(), se.fileno())
###

print("foo bar")

os.spawnve("P_WAIT", "/bin/ls", ["/bin/ls"], {})
os.execve("/bin/ls", ["/bin/ls"], os.environ)

El archivo "a.log" debe ser idéntico al que se muestra en la pantalla.

Respuestas a la pregunta(16)

Su respuesta a la pregunta