【问题标题】:Python subprocess stdout does not readPython子进程标准输出不读取
【发布时间】:2023-05-08 06:35:01
【问题描述】:

我正在尝试通过 python 运行 gnuplot。

我可以发送和运行命令,但无法读取来自应用程序的警告或错误消息。它只是在这里等待:“self.proc.stdout.readline()”。

这是我的全部代码:

from subprocess import PIPE, Popen

import fcntl, os

class Gnuplot:
    def __init__(self, debug=True):
        self.debug = debug
        if self.debug:
            print 'Initializing ...\n' 

        self.proc = Popen(['gnuplot','-persist'],stdin=PIPE, stdout=PIPE, stderr=PIPE)  
        fcntl.fcntl(self.proc.stderr.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)

    def communicate(self, cin='\n'):
        self.proc.stdin.write(cin+'\n')
        cout, cerr = '', ''
        print "lol"
        if self.proc.stdout:
            cout = self.proc.stdout.readline()
            self.proc.stdout.close()
            print cout
        elif self.proc.stderr:
            cerr = self.proc.stderr.read()
            self.proc.stderr.close()
            print cerr


if __name__ == '__main__':
    g = Gnuplot()   
    g.communicate("set parameter\n")
    g.communicate("plot sin(x)\n")     

它只是在这里等待:

cout = self.proc.stdout.readline()

【问题讨论】:

    标签: python pipe subprocess communicate


    【解决方案1】:

    警告和错误通常在标准错误流而不是标准输出上输出(例如,这可以防止结果与警告消息混淆)。因为您首先从stdout 读取,并且没有给出输出,所以您没有到达您从stderr 读取的部分。

    注意,subprocess recommends against accessing the streams directly:

    警告:使用communicate() 而不是.stdin.write、.stdout.read 或 .stderr.read 以避免由于任何其他操作系统管道导致的死锁 缓冲区填满并阻塞子进程。

    您可能希望按照建议使用process.communicate()。这为您提供了一个 stdout_data, stderr_data 的元组,因此只需抓住第二个即可获取您的警告和错误。这回避了必须手动读取输出的问题,以及类似的问题。

    【讨论】: