2012-07-03 3 views
3

Я создаю процесс в python, используя подпроцесс, и хочу читать выходные данные из программы, используя каналы. Программа на C++, похоже, не закрывает трубу, даже когда явное указание закрыть ее.Трубы между Python и C++ не закрываются

#include <cstdlib> 
#include <ext/stdio_filebuf.h> 
#include <iostream> 

int main(int argc, char **argv) { 
    int fd = atoi(argv[1]); 
    __gnu_cxx::stdio_filebuf<char> buffer(fd, std::ios::out); 
    std::ostream stream(&buffer); 
    stream << "Hello World" << std::endl; 
    buffer.close(); 
    return 0; 
} 

Я призываю эту небольшую программу с этим питоном сниппета: метод

import os                       
import subprocess                     

read, write = os.pipe()                   
proc = subprocess.Popen(["./dummy", str(write)])             
data = os.fdopen(read, "r").read()                 
print data                       

Считанные() не возвращает, как ФД не закрыты. Проблема с открытием и закрытием записи fd в python решает проблему. Но мне кажется, что это взломан. Есть ли способ закрыть fd в моем C++-процессе?

Большое спасибо!

ответ

5

нерест дочернего процесса на Linux (все POSIX ОС, на самом деле), как правило, осуществляются с помощью fork и exec. После fork оба процесса имеют открытый файл. Процесс C++ закрывает его, но файл остается открытым до тех пор, пока родительский процесс не закроет fd. Это нормально для кода с использованием fork и обычно обрабатывается оберткой около fork. Прочтите страницу man для pipe. Я думаю, что python не знает, какие файлы передаются ребенку, и, следовательно, не знает, что закрыть в родительском и дочернем процессах.

+0

Интересно. Значит, вы закрываете дескриптор файла после создания объекта «Popen»? – krlmlr

+0

@ user946850: см. Примерный код на http://linux.die.net/man/2/pipe –

+4

См. Также пример в документах Python: http://docs.python.org/library/subprocess.html. # replace-shell-pipe. «Вызов p1.stdout.close() после запуска p2 важен для того, чтобы p1 получил SIGPIPE, если p2 выходит до p1». Это означает, что да, пожалуйста, закройте дескриптор процесса Python. – krlmlr

3

Дескрипторы файла POSIX являются локальными для процесса. Дескриптор файла write из инструмента Python недействителен в процессе C++.

Возможно, самый простой способ будет иметь процесс C++ написать свой вывод stdout (как cout <<) и Python вызов Popen с помощью stdout=PIPE и чтения proc.stdout (или использовать proc.communicate() вместо использования fdopen. Это должно работать в Windows, тоже.

Для прохождения дескриптора файла в качестве аргумента командной строки см Ben Voigt's answer.

+0

Я не помню, каковы условия, но можно наследовать файловые дескрипторы. –

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