2013-06-19 3 views
3

У меня эта проблема беспокоит меня в течение некоторого времени, и я не могу найти решение для нее, я использую subprocess.Popen() для доступа к C++, которое делает некоторые тяжелые вычисления для меня, но оно продолжает замерзать на Popen(). Stdout.read(); вот код питона:Подпроцесс freezes popen(). Stdout.read

process = subprocess.Popen(['/path/to/my/executable'], shell=False, 
stdout=subprocess.PIPE, stdin=subprocess.PIPE) 
process.stdin.write("Some String") 
print process.stdout.read()#It freezes here 

и вот с ++ код:

код
int main(int argc, char** argv) { 
    ...Prep work... 
    while (1) { 
     string input; 
     cin>>input; 
    ...Some Work ... 
     cout<< response; 
    } 
} 

C++ прекрасно работает в оболочке, но я не могу понять, почему она замерзает на питона

+0

Поскольку скрипт Python ожидает завершения подпроцесса? –

+0

Могу ли я прочитать cout, не дожидаясь завершения процесса? –

+0

Если 'process.stdin' забуферирован, ваши записи могут быть не сразу видны для программы на C++. Аналогично, если 'process.stdout' буферизуется, записи C++ могут быть не сразу видны вашей программе Python. – chepner

ответ

3

Используйте communicate() вместо:

import subprocess 
process = subprocess.Popen(['app'], shell=False, 
          stdout=subprocess.PIPE, 
          stdin=subprocess.PIPE) 
out, err = process.communicate("Some String") 
print out 

Кроме того, убедитесь, что йо u завершите свой C++-процесс в какой-то момент. Например, когда вы дойдете до конца вашего входного потока:

#include <string> 
#include <iostream> 
using namespace std; 

int main(int argc, char** argv) { 
    //...Prep work... 
    while (cin) { // <-- Will eventually reach the end of the input stream 
     string input; 
     cin >> input; 
     //...Some Work ... 
     string response = input; 
     cout << response; 
    } 
} 

Существует предупреждение для этого в документации питона: http://docs.python.org/2/library/subprocess.html#subprocess.Popen.stdin (справа выше)

Он объясняет, что, когда вы пишете на внешнее приложение , данные могут быть помещены в очередь. Кроме того, вывод внешнего приложения также будет помещен в очередь. Связь() будет «очищать» содержимое, которое вы отправляете во внешнее приложение, и ждать, пока ваше приложение не завершится.

Используя communicate(), вы получите весь внешний выход приложения в памяти. Если это непрактично (например, огромный вывод), вы можете писать или читать с использованием объектов stdin и stdout. Вы должны позаботиться о не «запирании»:

import subprocess 

process = subprocess.Popen(['app'], shell=False, 
          stdout=subprocess.PIPE, 
          stdin=subprocess.PIPE) 
process.stdin.write("Some String") 
process.stdin.close() # <-- Makes sure the external app gets an EOF while 
         #  reading its input stream. 
for line in process.stdout.readlines(): 
    print line 

Но даже с этой техникой, убедитесь, что вход вы даете внешнему приложение достаточно мал, чтобы избежать блокировок при записи.

Если ваш вход также довольно большой, вам нужно убедиться, что ваши чтения и записи не блокируются. Использование потоков, скорее всего, будет хорошим выбором.

+0

Спасибо за ваш ответ @Teebrin, я попробовал, и теперь я Ошибка при получении этой ошибки, err = process.communicate (команда) Файл «/usr/lib/python2.7/subprocess.py ", строка 806, в сообщении return self._communicate (ввод) Файл" /usr/lib/python2.7/subprocess.py ", строка 1382, в _communicate stdout, stderr = self._communicate_with_poll (ввод) Файл «/usr/lib/python2.7/subprocess.py», строка 1456, в _communicate_with_poll data = os.read (fd, 4096) MemoryError –

+0

Ваше внешнее приложение, вероятно, выводит огромное количество данных. ответ, чтобы дать пример того, как читать огромный результат. На самом деле, он напоминает немного больше вашего исходного кода. – Teebrin

0

Обычно нам нужно неблокирующая IO, 1) читать все ответы, пока не больше данных, а затем 2) излучает что-то подпроцесс, повторять 1-2 Использование потоков также помогут.

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