2016-12-06 4 views
1

В моей программе python у меня есть два subprocesses, соединенных pipe и один подключенный к stdin, а другой подключен к stdout. Моя проблема в том, что когда поток данных заканчивается, подпроцессы зависают, пока я не нажму ctrl+c. Мне кажется, что подпроцессы закрывают мою трубу. Если бы я мог сказать, когда данные, проходящие через трубу, я мог бы закрыть ее вручную.Как сказать, когда данные по трубе закончились

def write(tag_name): 
    p_r, p_w = os.pipe() 
    pv = subprocess.Popen('pv', stdin=None, stdout=p_w) 
    dd = subprocess.Popen('dd bs=64k of=/dev/nst0'.split(), stdin=p_r, stdout=None) 
    dd.wait() 

ответ

1

Только не используйте os.pipe(), вы можете передать подпроцесс stdout непосредственно к другому процессу stdin, как это:

def write(tag_name): 
    pv = subprocess.Popen('pv', stdin=None, stdout=subprocess.PIPE) 
    dd = subprocess.Popen('dd bs=64k of=/dev/nst0'.split(), stdin=pv.stdout, stdout=None) 
    dd.wait() 

Когда первые концы команды, труба сломана (в отличие от os.pipe() которые необходимо закрыть вручную), поэтому он также завершает вторую команду, и сценарий может продолжать/завершаться.

Я проверил простую команду на трубе, и с os.pipe() он блокирует в конце, как описано, но вышел, когда первый процесс завершился моими изменениями.

+0

Я получаю 'OSError: [Errno 9] Плохой дескриптор файла' на строке' pv'. –

+0

Глядя на руководство python 'subprocess.STDOUT', можно использовать только как аргумент' Popen.stderr'. Передача 'stdout = subprocess.PIPE' работает, как вы сказали. –

+0

извините, опечатка !! исправлено на 'subprocess.PIPE' –

0

Здесь вам нужно неблокирующее решение. Посмотрите на мое решение: https://github.com/vesellov/bitdust.devel/blob/master/system/nonblocking.py

А вы можете назвать это так (не тестировал код):

import nonblocking, time 
p = nonblocking.Popen('pv'.split(), shell=True,) 
p.make_nonblocking() 
while 1: 
    if p.state() == nonblocking.PIPE_CLOSED: 
     # pipe closed, stop 
     return break 
    if p.state() == nonblocking.PIPE_READY2READ: 
     newchunk = p.recv(1024) 
     if newchunk == '': 
      # EOF reached, stop 
      break 
     # do something with the data here 
     # you can send it to second stream 
    try: 
     time.sleep(0.01) 
    except KeyboardInterrup: 
     break 

Так что, когда вы звоните dd.wait() он будет блокировать, то есть почему ваш Ctrl-C не работает. Вам нужно иметь дело с этим вручную .... неблокирующая потоковая передача - это не тривиальная история в Python. Выезд Twisted project, вы можете найти много классных вещей :-)

+0

Интересное решение, только недостатком является то, что он имеет пропускную способность, ограниченную 100 КБ/с. В моем случае 'dd.wait()' не останавливает 'Ctrl-C', на самом деле нажатие' Ctrl-C' заставляет сборщик мусора собираться, а подпроцессы - выйти чисто. –

+0

Да, вы можете отрегулировать 'time.sleep()' интервал по мере необходимости. –

 Смежные вопросы

  • Нет связанных вопросов^_^