当前位置: 动力学知识库 > 问答 > 编程问答 >

Reading from stdin in Python subprocess hangs in C++/Python IPC

问题描述:

I am working on a C++ application which starts a Python subprocess and tries to establish a communication between parent (C++) and child (Python). In particular I am writing the Python part in order to integrate with the C++ application which I haven't written and I cannot change. I already implemented a socket solution to handle the communication but I need also to support the communication using pipes.

My problem is that I can write from Python to stdout and the message is received by the C++ application. However the Python subprocess can't read the message sent by the parent process. I tried to extrapolate the parts of the code that I think are the most relevant to describe the problem:

C++

void startSubprocess(char* program, char** arguments)

{

int p_stdout;

int p_stdin;

int p_stderr;

int out[2];

int in[2];

int err[2];

char** arguments;

char* program;

pipe(out);

pipe(in);

pipe(err);

posix_spawn_file_actions_init(&action);

posix_spawn_file_actions_addclose(&action, out[1]);

posix_spawn_file_actions_addclose(&action, in[0]);

posix_spawn_file_actions_addclose(&action, err[0]);

posix_spawn_file_actions_adddup2(&action, out[0], 0);

posix_spawn_file_actions_adddup2(&action, in[1], 1);

posix_spawn_file_actions_adddup2(&action, err[1], 2);

std::vector<char *> vars_c(vars.size() + 1);

for (std::size_t i = 0; i != vars.size(); ++i) {

vars_c[i] = &vars[i][0];

}

vars_c[vars.size()] = NULL;

string cwd = __getcwd();

if (directory.size() > 0)

chdir(directory.c_str());

if (posix_spawnp(&pid, program, &action, NULL, arguments, vars_c.data())) {

cleanup();

pid = 0;

if (directory.size() > 0) chdir(cwd.c_str());

return false;

}

if (directory.size() > 0) chdir(cwd.c_str());

p_stdin = out[1];

p_stdout = in[0];

p_stderr = err[0];

}

void write(const char* buf, int len)

{

write(p_stdout, buf, len);

}

void read(char* buf, int len)

{

read(p_stdin, buf, len);

}

Python

def writeMsg(msg):

sys.stdout.write(msg)

sys.stdout.flush()

def readMsg():

msg = sys.stdin.read()

When I run the application the parent process (C++) reads the message sent by the Python subprocess. After that the Python subprocess is not able to read from sys.stdin . It waits forever till the timeout.

When I run the C++ application I can see that out = [3,4] and in=[5,6] so p_stdin=6 and p_stdout=3. I am testing the application in Ubuntu 14.04.

I have been trying few other approaches (using os.fdopen and os.read) but without success. Any suggestion to solve this problem is welcomed. Thanks!

EDIT

I have realised that I skipped some important information to understand the problem. The main application and the Python subprocess need to continuosly communicate and read and write message to send and receive in a loop till termination. The code looks something like this (just for description purpose):

C++

int communicate()

{

// skip var init etc

// launch subprocess

startSubprocess(program, arguments);

while(1)

{

// read message sent by subprocess

read(msg, len);

if(msg == "quit")

break;

// part of the code that generates msg2

// send a message to subproc

write(msg2, len2);

}

return 1;

}

Python

def communicate():

while True:

# generate msg to send to C++

writeMsg(msg)

msgRcv = readMsg()

if msgRcv == 'quit':

break

return

网友答案:

I have realised that sys.stdin.read() hangs till EOF before returning the message. By replacing msg = sys.stdin.read() with

msg = sys.stdin.readline() 

my application works as expected. The messages sent by the application are separated by newline '\n' character so this approach works for me. In other cases I think that reading one character at a time using

msg += sys.stdin.read(1) 

will avoid the program to hang waiting for EOF.

There are already several answers about this difference between read and readline. Unfortunately during my tests when I tried readline the client was terminated by the parent process before reading.

分享给朋友:
您可能感兴趣的文章:
随机阅读: