How to redirect stdout for a subprocess?

11,125

Solution 1

Like unwind said, you cannot change the file descriptor that the child process is writing its output to.

What you can do, is read the output from the child process in your python script and then write it back to whatever file you want to. E.g.:

proc = subprocess.Popen(path, 0, None, subprocess.PIPE, subprocess.PIPE, None)

for l in proc.stdout.readlines():
  output_file.write(l)

Obivously, you'll need to figure out how control should behave in your app, i.e. can you do the writing from the main thread, when should the main thread return from StartProc() in that case, or do you have to do the writing from another thread so that the main thread can return from StartProc() immediately.

Solution 2

You can't. Once the process is started, its stdout is nothing you can change from the outside. You need to get inside that process' space to muck with its file descriptors.

If you have a way (in MyReset() I guess) to talk to the running process, perhaps you can engineer a way to pass a new filename for it to (re)open as its stdout, that way.

Solution 3

There are subtle problems/bugs in python related to subprocess.PIPE: http://bugs.python.org/issue1652

Apparently this was fixed in python3+, but not in python 2.7 and older. For that you need to use: code.google.com/p/python-subprocess32/

Share:
11,125
MA1
Author by

MA1

Full Stack Python Engineer 4 year experience in Python. 2 year experience in Django, Javascript, BackboneJS.

Updated on June 04, 2022

Comments

  • MA1
    MA1 almost 2 years
    def StartProc(dir, parm):
        global proc    
    
        proc_log = open(dir + os.sep + "MyLog.txt","w")  #new path for each file
    
        if parm:
            proc = subprocess.Popen(path, 0, None, subprocess.PIPE, proc_log, None)
        else:
            MyReset(proc)                     #reset the process(proc) to its default values
            proc.stdout = proc_log            #no effect
            print "fptr ", proc.stdout
        #endif
    #enddef
    
    prm = True
    
    for i in range(0, 5):
        StartProc(i, prm)
        prm = False
    #endfor
    

    What I want to do is to start an executable only once, but on each iteration I want to redirect the process output to a different file. What is happening, is that files are created in the different path, but output is redirected to the file that is created first time.

    Note: MyReset() initializes the process (executable) to its default values after the first iteration.

    Will the following line change the process stdout to new file?

    proc.stdout = proc_log