live output from subprocess command

后端 未结 16 1459
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-22 08:16

I\'m using a python script as a driver for a hydrodynamics code. When it comes time to run the simulation, I use subprocess.Popen to run the code, collect the

16条回答
  •  南旧
    南旧 (楼主)
    2020-11-22 08:56

    A good but "heavyweight" solution is to use Twisted - see the bottom.

    If you're willing to live with only stdout something along those lines should work:

    import subprocess
    import sys
    popenobj = subprocess.Popen(["ls", "-Rl"], stdout=subprocess.PIPE)
    while not popenobj.poll():
       stdoutdata = popenobj.stdout.readline()
       if stdoutdata:
          sys.stdout.write(stdoutdata)
       else:
          break
    print "Return code", popenobj.returncode
    

    (If you use read() it tries to read the entire "file" which isn't useful, what we really could use here is something that reads all the data that's in the pipe right now)

    One might also try to approach this with threading, e.g.:

    import subprocess
    import sys
    import threading
    
    popenobj = subprocess.Popen("ls", stdout=subprocess.PIPE, shell=True)
    
    def stdoutprocess(o):
       while True:
          stdoutdata = o.stdout.readline()
          if stdoutdata:
             sys.stdout.write(stdoutdata)
          else:
             break
    
    t = threading.Thread(target=stdoutprocess, args=(popenobj,))
    t.start()
    popenobj.wait()
    t.join()
    print "Return code", popenobj.returncode
    

    Now we could potentially add stderr as well by having two threads.

    Note however the subprocess docs discourage using these files directly and recommends to use communicate() (mostly concerned with deadlocks which I think isn't an issue above) and the solutions are a little klunky so it really seems like the subprocess module isn't quite up to the job (also see: http://www.python.org/dev/peps/pep-3145/ ) and we need to look at something else.

    A more involved solution is to use Twisted as shown here: https://twistedmatrix.com/documents/11.1.0/core/howto/process.html

    The way you do this with Twisted is to create your process using reactor.spawnprocess() and providing a ProcessProtocol that then processes output asynchronously. The Twisted sample Python code is here: https://twistedmatrix.com/documents/11.1.0/core/howto/listings/process/process.py

提交回复
热议问题