How to duplicate sys.stdout to a log file?

前端 未结 17 898
醉酒成梦
醉酒成梦 2020-11-22 06:54

Edit: Since it appears that there\'s either no solution, or I\'m doing something so non-standard that nobody knows - I\'ll revise my question to also ask: What is the best w

17条回答
  •  一向
    一向 (楼主)
    2020-11-22 07:43

    Since you're comfortable spawning external processes from your code, you could use tee itself. I don't know of any Unix system calls that do exactly what tee does.

    # Note this version was written circa Python 2.6, see below for
    # an updated 3.3+-compatible version.
    import subprocess, os, sys
    
    # Unbuffer output (this ensures the output is in the correct order)
    sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
    
    tee = subprocess.Popen(["tee", "log.txt"], stdin=subprocess.PIPE)
    os.dup2(tee.stdin.fileno(), sys.stdout.fileno())
    os.dup2(tee.stdin.fileno(), sys.stderr.fileno())
    
    print "\nstdout"
    print >>sys.stderr, "stderr"
    os.spawnve("P_WAIT", "/bin/ls", ["/bin/ls"], {})
    os.execve("/bin/ls", ["/bin/ls"], os.environ)
    

    You could also emulate tee using the multiprocessing package (or use processing if you're using Python 2.5 or earlier).

    Update

    Here is a Python 3.3+-compatible version:

    import subprocess, os, sys
    
    tee = subprocess.Popen(["tee", "log.txt"], stdin=subprocess.PIPE)
    # Cause tee's stdin to get a copy of our stdin/stdout (as well as that
    # of any child processes we spawn)
    os.dup2(tee.stdin.fileno(), sys.stdout.fileno())
    os.dup2(tee.stdin.fileno(), sys.stderr.fileno())
    
    # The flush flag is needed to guarantee these lines are written before
    # the two spawned /bin/ls processes emit any output
    print("\nstdout", flush=True)
    print("stderr", file=sys.stderr, flush=True)
    
    # These child processes' stdin/stdout are 
    os.spawnve("P_WAIT", "/bin/ls", ["/bin/ls"], {})
    os.execve("/bin/ls", ["/bin/ls"], os.environ)
    

提交回复
热议问题