Эта проблема беспокоит меня в течение некоторого времени, и я не могу найти решение этой проблемы, я использую subprocess.Popen () для доступа к приложению C ++, которое выполняет для меня тяжелые вычисления, но это продолжает зависать на Popen (). stdout.read ();
вот код Python:
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
и вот код C ++:
int main(int argc, char** argv) {
...Prep work...
while (1) {
string input;
cin>>input;
...Some Work ...
cout<< response;
}
}
Код C ++ отлично работает в оболочке, но я не могу понять, почему он зависает на Python
использование communicate()
вместо:
import subprocess
process = subprocess.Popen(['app'], shell=False,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE)
out, err = process.communicate("Some String")
print out
Кроме того, убедитесь, что вы завершили свой процесс 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;
}
}
Для этого есть предупреждение в документации Python:
http://docs.python.org/2/library/subprocess.html#subprocess.Popen.stdin (прямо над)
Это объясняет, что когда вы пишете во внешнее приложение, данные могут быть помещены в очередь. Кроме того, вывод вашего внешнего приложения, скорее всего, также будет помещен в очередь. Функция connect () будет «сбрасывать» содержимое, которое вы отправляете во внешнее приложение, и ждать, пока ваше приложение не завершится.
С помощью 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
Но даже с этой техникой убедитесь, что ввод, который вы вводите во внешнее приложение, достаточно мал, чтобы избежать блокировки во время записи.
Если ваш ввод также довольно большой, вы должны убедиться, что ваши чтения и записи не блокируются. Тогда использование потоков, скорее всего, будет хорошим выбором.
Обычно нам нужен неблокирующий ввод-вывод,
1) читать все ответы до тех пор, пока не останется данных
2) что-то выдать в подпроцесс,
повторяя 1-2
Использование потоков также поможет.