Стандартный вывод подпроцесса Python не читается

Я пытаюсь запустить gnuplot через python.

Я могу отправлять и запускать команды, но не могу читать предупреждения или сообщения об ошибках из приложения. Он просто ждет здесь: "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()

person user3817833    schedule 22.11.2014    source источник


Ответы (1)


Предупреждения и ошибки обычно выводятся в стандартный поток ошибок, а не в стандартный вывод (например, это предотвращает смешение результатов с предупреждающими сообщениями). Поскольку вы сначала читаете из stdout, а вывод не выдается, вы не попадаете в ту часть, где вы читаете из stderr.

Обратите внимание, что subprocess не рекомендует обращаться к потокам напрямую:

Предупреждение: используйте коммуникацию(), а не .stdin.write, .stdout.read или .stderr.read, чтобы избежать взаимоблокировок из-за заполнения любого другого буфера каналов операционной системы и блокировки дочернего процесса.

Вероятно, вы захотите использовать process.communicate(), как было предложено. Это дает вам кортеж stdout_data, stderr_data, поэтому просто возьмите второй, чтобы получить предупреждения и ошибки. Это позволяет избежать необходимости чтения вывода вручную и подобных проблем.

person Gareth Latty    schedule 22.11.2014