Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何从子流程获取实时输出流?_Python_Python 3.x_Subprocess_Pipe - Fatal编程技术网

Python 如何从子流程获取实时输出流?

Python 如何从子流程获取实时输出流?,python,python-3.x,subprocess,pipe,Python,Python 3.x,Subprocess,Pipe,我试图从正在运行的Python子进程中提取输出。为了简单起见,我创建了一个C可执行文件,它每秒只打印0、1、2等,并无限期运行 我使用的Python脚本,以及其他一些类似想法的变体,似乎都在5分钟内什么也不做,然后一次将300行打印到终端。相反,我试图让它每秒打印一行。使用Python 3.5 import subprocess import os import sys from time import sleep def start_program(): args = ['./te

我试图从正在运行的Python子进程中提取输出。为了简单起见,我创建了一个C可执行文件,它每秒只打印0、1、2等,并无限期运行

我使用的Python脚本,以及其他一些类似想法的变体,似乎都在5分钟内什么也不做,然后一次将300行打印到终端。相反,我试图让它每秒打印一行。使用Python 3.5

import subprocess
import os
import sys
from time import sleep 

def start_program():
    args = ['./test_program']
    p = subprocess.Popen(args, stdout=subprocess.PIPE, universal_newlines=True, bufsize=1)
    return p

def print_output(p):
    for line in p.stdout:
        print(line, end='')

def main():
    p = start_program()
    print_output(p)

main()

问题是,您的C程序检测到输出不是TTY,因此正在对其进行缓冲。我假设您的C程序是这样的:

#包括
#包括
内部主(空){
对于(int i=0;i<300;++i){
printf(“%d\n”,i);
睡眠(1);
}
}
有两种方法可以修复它:

  • 编辑你的C程序做
    fflush(stdout)
    循环的每次迭代或
    setvbuf
    以在开始时禁用缓冲
  • 编辑Python程序以将C程序包装在
    stdbuf
    中,如下所示:
    args=['stdbuf'、'-oL'、'./test_program']

  • 基本问题由@Joseph Sible Restore Monica描述,但您也可能面临临时阻塞问题。对进程中的行使用
    process.stdout.readline()
    。stdout:
    使脚本等待
    process.stdout
    中的新行

    通过在读取数据之前分析数据的可用性,您可以在无需等待的情况下实时接收和处理数据

    主文件:

    import subprocess
    from time import sleep
    
    process = subprocess.Popen(('python', 'subTest.py'), stdout=subprocess.PIPE)
    
    while True:
        sleep(0.7) #do smth
        bytes_number = process.stdout.seek(0, 2)
        if bytes_number:
            print('number of new bytes: ', bytes_number)
            process.stdout.seek(0, 0)
            print(process.stdout.read(bytes_number))
        if process.poll() is not None and not bytes_number:
            break
    
    print('done!')
    
    from sys import stdout
    from time import sleep
    
    for i in range(10):
        sleep(0.2) #do smth
        stdout.write(str(i) + '/')
        stdout.flush()
    
    如果运行另一个python脚本而不是C-可执行文件,则还需要使用
    stdout.flush()
    (python中的模拟
    fflush(stdout)

    子流程文件:

    import subprocess
    from time import sleep
    
    process = subprocess.Popen(('python', 'subTest.py'), stdout=subprocess.PIPE)
    
    while True:
        sleep(0.7) #do smth
        bytes_number = process.stdout.seek(0, 2)
        if bytes_number:
            print('number of new bytes: ', bytes_number)
            process.stdout.seek(0, 0)
            print(process.stdout.read(bytes_number))
        if process.poll() is not None and not bytes_number:
            break
    
    print('done!')
    
    from sys import stdout
    from time import sleep
    
    for i in range(10):
        sleep(0.2) #do smth
        stdout.write(str(i) + '/')
        stdout.flush()
    

    这是我早些时候尝试过的想法之一,但不幸的是,子流程的stdout不可查找,因此此解决方案在这里不可行。