deadParrot
deadParrot

Reputation: 147

Python 3 failing to send message to C# subprocess

Fairly new to python and currently using Python 3.5.2. I have a subprocess where I need to monitor the output, process it and display it via kivy. This works fine.

But there comes a point where the subprocess needs a reply to continue or exit. This is where I am utterly stuck.

chimp_cmd = 'sudo /usr/bin/mono ' + os.getcwd() + '/aDotNet.exe ' + aVeryLongListofParam    # aVeryLongListofParam is read from a file
child = subprocess.Popen([chimp_cmd], 
                                        shell=True, 
                                        stdout=subprocess.PIPE, 
                                        stderr=subprocess.STDOUT,
                                        stdin=subprocess.PIPE,
                                        bufsize=0) # no difference with bufsize set to 1
 # while loop that reads in the data    

     # do funky stuff with the output data, (this works and relies on a lot of starts with comparisons)

     if ( (b''.join(MyOutputLineList).decode("utf-8) ).startswith("Would you like"):

         # wait for the thread that gets the response - this works

         if usrReply = UsrKeyReply.no:
             print("received user no")        # we get to here 
             # attempts at sending a reply:
             ret_value = child.stdin.write(b'n\n') # this doesn't work for me
             print(ret_value)
             print("test1") 
             os.system('pidof mono')        # for debug

         elif usrReply = UsrKeyReply.yes:
             print("received user yes")  # also get to this point 
             stdout, stderr = child.communicate(input=b'n\n')[0]
             # child.stdin.flush()  <-- this hangs the code
             print("test2")                 # doesn't work for me either

Other details. On Ubuntu. The python scirpt is invoked with:

sudo python3 myscript.py    

Yes it needs to be sudo because mono needs access to a USB port.

DotNet.exe is third party

DotNet.exe works fine if invoked directly from the command line.

I know that the message does not get back to the subprocess because apart from nothing happens, I can open another terminal and monitor the child with:

sudo strace -p <mono's PID>

Here I can see the exe going through the motions and playing nicely with the python script, and I see the prompt "Would you like..."

When the python script reaches the point of sending back the reply the child doesn't terminate (when 'n') or continue (when 'y')

Help!

As suggested by @Hermann I have tried changing to:

bufsize=1,
universal_newlines=True)

also amended the reply to

stdout, stderr = child.communicate(input='n\n')[0]
child.stdin.flush()

The script hangs after this.

Any more ideas?

Upvotes: 1

Views: 528

Answers (2)

deadParrot
deadParrot

Reputation: 147

After further investigation, it turns out that python does indeed send data to the subprocess. The problem lies with how the input is handled on the C# side.

Console.ReadKey().Key /* this will not work with python subprocess piped stdin */

versus

piped_reply = Console.ReadLine() /* will work with python piped stdin */

See SO question: C# Console receive input with pipe

Upvotes: 1

Hermann
Hermann

Reputation: 637

You can flush the write buffer explicitly by calling child.stdin.flush().

Alternatively, you can try adding bufsize=1 and universal_newlines=True in your subprocess.Popen call for switching line-buffered mode. Note that the behaviour varies wildly accross Python 3 versions as mentioned in the various comments in subprocess stdin buffer not flushing on newline with bufsize=1.

Upvotes: 1

Related Questions