Сломанный канал из подпроцесса.Popen.communciate () с помощью stdin - PullRequest
3 голосов
/ 15 января 2010

У меня странная проблема при использовании subprocess.Popen.communicate (). Для фона я хочу выполнить приложение из моего скрипта Python. Когда я запускаю программу из командной строки, я делаю это так (UNIX):

$ echo "input text" | /path/to/myapp

Из моего скрипта я также хочу передать данные в приложение. Итак, я попробовал следующее. Но я получаю сообщение об ошибке "сломанная труба", когда пытаюсь отправить вход с помощью connect ():

>>> cmd = ['/path/to/myapp']
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
>>> out,err = p.communicate('input text')
Traceback (most recent call last):
  File "", line 1, in 
  File "/usr/lib/python2.5/subprocess.py", line 670, in communicate
    return self._communicate(input)
  File "/usr/lib/python2.5/subprocess.py", line 1223, in _communicate
    bytes_written = self._write_no_intr(self.stdin.fileno(), buffer(input, input_offset, 512))
  File "/usr/lib/python2.5/subprocess.py", line 1003, in _write_no_intr
    return os.write(fd, s)
OSError: [Errno 32] Broken pipe

Чтобы сделать ситуацию более странной, если я пропущу входные данные, я не получу никаких ошибок. Тем не менее, это не очень хороший обходной путь, потому что приложение требует ввода для работы.

>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
>>> out,err = p.communicate()
>>> print out
[error from myapp regarding lack of input]

Есть идеи, что мне не хватает?

1 Ответ

3 голосов
/ 15 января 2010

Ваши наблюдения показывают, что myapp завершает работу без чтения (всех) входных данных. Не зная ничего о myapp, это сложно подтвердить, но рассмотрим, например,

$ echo 'hello world' | tr 'l' 'L'
heLLo worLd

сейчас ...:

>>> cmd = ['/usr/bin/tr']
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
>>> out,err = p.communicate('hello world')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.5/subprocess.py", line 668, in communicate
    return self._communicate(input)
  File "/usr/lib/python2.5/subprocess.py", line 1218, in _communicate
    bytes_written = self._write_no_intr(self.stdin.fileno(), buffer(input, input_offset, 512))
  File "/usr/lib/python2.5/subprocess.py", line 997, in _write_no_intr
    return os.write(fd, s)
OSError: [Errno 32] Broken pipe

, потому что ...:

>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
>>> /usr/bin/tr: missing operand
Try `/usr/bin/tr --help' for more information.

и если мы исправим ошибку:

>>> cmd = ['/usr/bin/tr', 'l', 'L']
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
>>> out,err = p.communicate('hello world')>>> print out
heLLo worLd
>>> print err
None

... это все исправляет. Что произойдет, если вы пропустите перенаправление stderr - видите ли вы какие-либо сообщения об ошибках от myapp ...?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...