Python 获取 subprocess.Popen 的实时输出

8,940 阅读1分钟

使用 subprocess.Popen 运行指令,实时获取输出

import subprocess

cmd = "ping www.baidu.com -w 5"
pipe = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, bufsize=1)

# 实时打印log
def print_log():
    # 当info为b''时停止
    for info in iter(pipe.stdout.readline, b''):
        print(info)


print_log()

使用 subprocess.Popen 运行指令,实时获取输出,10s 后关闭

import time
import subprocess

cmd = "ping www.baidu.com -t"
start_time = time.time()
pipe = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, bufsize=1)

# 实时打印log
def print_log():
    for info in iter(pipe.stdout.readline, b''):
        print(info)
        # 10s后关闭子进程
        if time.time() - start_time > 10:
            pipe.terminate()
            pipe.wait()
            break


print_log()

    只有产生输出时for info in iter(pipe.stdout.readline, "")才会进行遍历,否则会一直处于等待状态。

    设想该场景,windows系统下使用adb logcat | findstr START 对安卓设备的启动log进行监测。若直到20s才有输出,pipe.terminate()的生效时间会远远超过设定的10s,期间一直阻塞主进程。通过引入线程来解决该问题。

import time
import threading
import subprocess

# windows
cmd = "adb logcat | findstr START"
start_time = time.time()
pipe = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, bufsize=1)

# 实时打印log
def print_log():
    # 使用""代替b''防止提前中断
    for info in iter(pipe.stdout.readline, ""):
        print(info)

thread = threading.Thread(target=print_log)
thread.start()
# 等待十秒 
time.sleep(10)
{关闭线程thread}
# 关闭子进程
pipe.terminate()
pipe.wait()

python的threading模块并没有提供暂停,停止,恢复线程的方法。因此需要手动实现。详情见Python 实现关闭线程