Многократно общаться с процессом без разрыва трубы? - PullRequest
26 голосов
/ 17 июня 2010

Это не первый раз, когда у меня возникает эта проблема, и это действительно беспокоит меня.Всякий раз, когда я открываю канал с помощью модуля Python subprocess, я могу только communicate с ним один раз, как указано в документации: Read data from stdout and stderr, until end-of-file is reached

proc = sub.Popen("psql -h darwin -d main_db".split(),stdin=sub.PIPE,stdout=sub.PIPE)
print proc.communicate("select a,b,result from experiment_1412;\n")[0]
print proc.communicate("select theta,zeta,result from experiment_2099\n")[0]

Проблема здесь в том, что во второй раз Pythonне счастливДействительно, он решил закрыть файл после первого сообщения:

Traceback (most recent call last):
File "a.py", line 30, in <module>
    print proc.communicate("select theta,zeta,result from experiment_2099\n")[0]
File "/usr/lib64/python2.5/subprocess.py", line 667, in communicate
    return self._communicate(input)
File "/usr/lib64/python2.5/subprocess.py", line 1124, in _communicate
     self.stdin.flush()
ValueError: I/O operation on closed file

Разрешено ли многократное общение?

Ответы [ 4 ]

22 голосов
/ 18 июня 2010

Я думаю, что вы неправильно понимаете, общаться ...

http://docs.python.org/library/subprocess.html#subprocess.Popen.communicate

коммуникации отправляет строку другому процессу, а затем ожидает ее завершения ... (Как вы сказали, ожидает EOF прослушивания stdout & stderror)

Вместо этого вы должны сделать следующее:

proc.stdin.write('message')

# ...figure out how long or why you need to wait...

proc.stdin.write('message2')

(и если вам нужно получить stdout или stderr, вы бы использовали proc.stdout или proc.stderr)

4 голосов
/ 18 июня 2010

У меня была эта проблема раньше, и, насколько я мог судить, вы не могли бы сделать это с subprocess (что, я согласен, очень нелогично, если это правда).Я использовал pexpect (можно получить из PyPI).

2 голосов
/ 20 апреля 2012

Вы можете использовать:

proc.stdin.write('input')    
if proc.stdout.closed:
    print(proc.stdout)
1 голос
/ 20 октября 2015

Вы можете сделать это просто с помощью одного вызова communicate():

query1 = 'select a,b,result from experiment_1412;'
query1 = 'select theta,zeta,result from experiment_2099;'
concat_query = "{}\n{}".format(query1, query2)
print(proc.communicate(input=concat_query.encode('utf-8'))[0])

Ключевым моментом здесь является то, что вы пишете только один раз в stdin, а \n служит EOL. Ваш подпроцесс psql читает от stdin до \n, затем после завершения первого запроса он снова переходит к stdin, и к этому времени в буфере остается только вторая строка запроса.

...