Снова, тот же вопрос.
Причина - я все еще не могу заставить ее работать после чтения следующего:
Мой случай - то, что мне записали консольное приложение в C, позволяет, берут, например, этот код в цикле:
tmp = 0.0;
printf("\ninput>>");
scanf_s("%f",&tmp);
printf ("\ninput was: %f",tmp);
Это непрерывно читает некоторый вход и пишет некоторый вывод.
Мой код Python для взаимодействия с ним следующий:
p=subprocess.Popen([path],stdout=subprocess.PIPE,stdin=subprocess.PIPE)
p.stdin.write('12345\n')
for line in p.stdout:
print(">>> " + str(line.rstrip()))
p.stdout.flush()
До сих пор каждый раз, когда я считал форму p.stdout
это всегда ожидает, пока процесс не завершается и затем производит пустую строку. Я попробовал много материала - но тем не менее тот же результат.
Я попробовал Python 2.6 и 3.1, но версия не имеет значения - я просто должен заставить его работать где-нибудь.
Попытка записи в подпроцесс и чтения из подпроцесса по трубам сопряжена с трудностями из-за буферизации по умолчанию, которая происходит в обоих направлениях. Очень легко получить тупик, когда один или другой процесс (родительский или дочерний) читает из пустого буфера, пишет в полный буфер или выполняет блокирующее чтение из буфера, который ожидает данных, прежде чем системные библиотеки его очистят.
Для более скромных объемов данных может быть достаточно метода Popen.communicate()
. Однако, для данных, превышающих его буферизацию, вы, вероятно, получите остановленные процессы (подобно тому, что вы уже наблюдаете?)
Возможно, вам стоит поискать подробности об использовании модуля fcntl
и сделать один или другой (или оба) ваших файловых дескрипторов неблокирующими. В этом случае, конечно, вам придется обернуть все чтения и/или записи в эти файловые дескрипторы в соответствующую обработку исключений для обработки событий "EWOULDBLOCK". (Я не помню точное исключение Python, которое возникает при таких событиях).
Совершенно другим подходом было бы использование родительским процессом модуля select
и os.fork()
... а дочерним процессом - execve()
целевой программы после непосредственной обработки любого файла dup()ing. (По сути, вы повторно реализуете часть Popen()
, но с другой обработкой дескриптора родительского файла (PIPE).
Кстати, .communicate, по крайней мере в стандартных библиотеках Python 2.5 и 2.6, обрабатывает только около 64K удаленных данных (в Linux и FreeBSD). Это число может меняться в зависимости от различных факторов (возможно, включая параметры сборки, используемые для компиляции вашего интерпретатора Python, или версию libc, подключаемую к нему). Оно НЕ просто ограничено доступной памятью (несмотря на утверждение J.F. Sebastian об обратном), но ограничено гораздо меньшим значением.
Передать чтение из конвейера в отдельный поток, который сигнализирует, когда доступен фрагмент вывода:
Как я могу прочитать все доступные данные из subprocess.Popen.stdout (без блокировки)?