Python capture subprocess output after termination

前端 未结 3 1091
忘掉有多难
忘掉有多难 2021-01-12 17:06

I am trying to get subprocess output (on Windows) at the time the TimeoutExpired exception is raised. Any ideas?

try:
    proc = subprocess.run(cmd,timeout=3         


        
相关标签:
3条回答
  • 2021-01-12 17:10

    You need to use Popen and subprocess.PIPE in order to catch the process output when timeout expires. In particular Popen.communicate is what you need. Here is an example

    proc = subprocess.Popen(["ping", "192.168.1.1"],
                            stdout=subprocess.PIPE)
    
    try:
        output, error = proc.communicate(timeout=2)
    except subprocess.TimeoutExpired:
        proc.kill()
        output, error = proc.communicate()
        print(output)
        print(error)
    

    This will print the process output up to the time out expiration.

    0 讨论(0)
  • 2021-01-12 17:25

    If you cannot use timeout for whatever reason (one being a too old python version), here's my solution, which works with whatever python version:

    • create a thread that first waits then kills the subprocess object
    • in the main thread, read the lines in a loop.

    I'm using a python subprocess, running with the -u (unbuffered) option:

    transmitter.py: (test program which prints "hello xx" every 1/10th second)

    import time
    
    i=0
    while True:
        print("hello {}".format(i))
        i += 1
        time.sleep(0.1)
    

    the program itself (timeout set to 1.5 second):

    import subprocess,threading,time
    
    def timeout(p,timeout):
        time.sleep(timeout)
        p.kill()
    
    p = subprocess.Popen(["python","-u","transmitter.py"],stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
    t = threading.Thread(target=timeout,args=(p,1.5))
    t.start()
    output = []
    for line in p.stdout:
        output.append(line.decode())
    
    t.join()
    print("".join(output))
    

    In the end, after timeout, the program prints:

    hello 0
    hello 1
    hello 2
    hello 3
    hello 4
    hello 5
    hello 6
    hello 7
    hello 8
    hello 9
    hello 10
    hello 11
    hello 12
    hello 13
    hello 14
    
    0 讨论(0)
  • 2021-01-12 17:28

    Here is the way for capturing stdout for multiprocessing.Process

    import app
    import sys
    import io
    from multiprocessing import Process
    
    
    def run_app(some_param):
        sys.stdout = io.TextIOWrapper(open(sys.stdout.fileno(), 'wb', 0), write_through=True)
        app.run()
    
    app_process = Process(target=run_app, args=('some_param',))
    app_process.start()
    # Use app_process.termninate() for python <= 3.7.
    app_process.kill() 
    
    0 讨论(0)
提交回复
热议问题