Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Bidrectional Subprocess Communication

3 views
Skip to first unread message

Emanuele D'Arrigo

unread,
Dec 13, 2008, 3:19:29 PM12/13/08
to
Hi everybody,

I'm trying to replicate the positive results of the Client/Server
scripts from the thread "Bidirectional Networking", but this time
using a Process/SubProcess architecture.

The SubProcess, acting as a server, is working just fine. But the
Process executing the SubProcess, the client, somehow doesn't hear any
of the standard output from the SubProcess. What am I missing?

Below you can find the two short pieces of code. Thanks for your help!

Manu

-------------------------------------------
# serverTest.py
import sys

print("Starting Server!")

while True:
data = sys.stdin.readline().strip()
if(data):
print("SERVER RECV: '" + data + "'")

if(data == "Stop!"):
break

print("Server Stopped!")

-------------------------------------------
#clientTest.py

import sys
import threading
from time import sleep
from subprocess import Popen, PIPE

## Server Thread
class ListenerThread(threading.Thread):

def __init__(self, inChannel):
threading.Thread.__init__(self)
self.inChannel = inChannel

def run(self):
while True:
data = self.inChannel.readline().strip()
print("serverTest.py says: " + data)

print("Starting Client!")

server = Popen("python serverTest.py", stdin=PIPE, stdout=PIPE)

listenerThread = ListenerThread(server.stdout)
listenerThread.setDaemon(True)
listenerThread.start()

server.stdin.write("Something very meaningful!\n")
server.stdin.write("Stop!")

print("Client Stopped!")

Gabriel Genellina

unread,
Dec 13, 2008, 11:48:39 PM12/13/08
to pytho...@python.org
En Sat, 13 Dec 2008 18:19:29 -0200, Emanuele D'Arrigo <man...@gmail.com>
escribió:

> I'm trying to replicate the positive results of the Client/Server
> scripts from the thread "Bidirectional Networking", but this time
> using a Process/SubProcess architecture.
>
> The SubProcess, acting as a server, is working just fine. But the
> Process executing the SubProcess, the client, somehow doesn't hear any
> of the standard output from the SubProcess. What am I missing?

(Pipes don't work the same as sockets, although unix-like systems try hard
to hide the differences...)

- you have to close server.stdin when you don't have more data to send.
The server will see an end-of-file and knows it has to exit the loop. Same
thing on the client side.

- you have to wait until the server answers, else it will get a "broken
pipe" error or similar.

- end-of-file, in Python, is detected when a read/readline returns an
empty string

- you sent "Stop!" without a \n - readline() on the server side would wait
forever; it doesn't matter in the code below because server.stdin is
explicitely closed.

Below are the modified version of your programs:

#clientTest.py

import sys
import threading
from time import sleep
from subprocess import Popen, PIPE

## Server Thread
class ListenerThread(threading.Thread):

def __init__(self, inChannel):
threading.Thread.__init__(self)
self.inChannel = inChannel

def run(self):
while True:
data = self.inChannel.readline()

if not data: # data=='' means eof
break
data = data.strip()


print("serverTest.py says: " + data)

print("Starting Client!")

server = Popen("python serverTest.py", stdin=PIPE, stdout=PIPE)

listenerThread = ListenerThread(server.stdout)
listenerThread.start()

server.stdin.write("Something very meaningful!\n")
server.stdin.write("Stop!")

server.stdin.close() # notify server: no more data
listenerThread.join() # wait until server closes channel
print("Client Stopped!")

# serverTest.py
import sys

print("Starting Server!")

while True:
data = sys.stdin.readline()

if not data: # data=='' means eof
break

data = data.strip()


print("SERVER RECV: '" + data + "'")

if(data == "Stop!"):
break

print("Server Stopped!")


--
Gabriel Genellina

greg

unread,
Dec 14, 2008, 3:03:26 AM12/14/08
to
Gabriel Genellina wrote:

> (Pipes don't work the same as sockets, although unix-like systems try
> hard to hide the differences...)

BSD-based unixes implement pipes using socketpair(), so
pipes actually *are* sockets (or at least they used to be,
not sure whether it's still true).

--
Greg

Emanuele D'Arrigo

unread,
Dec 14, 2008, 6:37:38 AM12/14/08
to
On Dec 14, 4:48 am, "Gabriel Genellina" <gagsl-...@yahoo.com.ar>
wrote:

> - you have to close server.stdin when you don't have more data to send.
> The server will see an end-of-file and knows it has to exit the loop.
> Same thing on the client side.

Hi Gabriel, thanks for modifying the code to make it work. I've just
tried tinkering with it to see how far it would go. On your two
statements above: does this means that any data must be sent in one
batch and then the subprocess must shut down? What I was trying to
simulate is a client/server relationship through a subprocess, where
the server (the subprocess) keeps listening and the client sends data
when it wants to (and eventually viceversa). But when the
server.stdin.close() statement is issued, the pipe is closed for good
and can't be reopened (can it?).

> - you have to wait until the server answers, else it will get a "broken
> pipe" error or similar.

So, if I want to interrogate the subprocess multiple times I must end
and restart the ListenerThread multiple times then?

In the meantime, I better brush up on my streams... =)

Gabriel Genellina

unread,
Dec 14, 2008, 4:46:50 PM12/14/08
to pytho...@python.org
En Sun, 14 Dec 2008 09:37:38 -0200, Emanuele D'Arrigo <man...@gmail.com>
escribió:

> On Dec 14, 4:48 am, "Gabriel Genellina" <gagsl-...@yahoo.com.ar>


> wrote:
>> - you have to close server.stdin when you don't have more data to send.
>> The server will see an end-of-file and knows it has to exit the loop.
>> Same thing on the client side.
>
> Hi Gabriel, thanks for modifying the code to make it work. I've just
> tried tinkering with it to see how far it would go. On your two
> statements above: does this means that any data must be sent in one
> batch and then the subprocess must shut down? What I was trying to
> simulate is a client/server relationship through a subprocess, where
> the server (the subprocess) keeps listening and the client sends data
> when it wants to (and eventually viceversa). But when the
> server.stdin.close() statement is issued, the pipe is closed for good
> and can't be reopened (can it?).

No, not at all. You can keep writing things to the pipe - as long as the
read side keeps reading, there is no limit on how much data you can send.
Just make sure you close the writing side of the pipe when you have no
more data to send, to signal the other side it's OK to exit the read loop.

>> - you have to wait until the server answers, else it will get a "broken
>> pipe" error or similar.
>
> So, if I want to interrogate the subprocess multiple times I must end
> and restart the ListenerThread multiple times then?

No, I mean, since your example is bidirectional, the parent process must
still be alive and able to read when the subprocess replies. Given this
sequence:

parent writes "hi sub!"
child reads "hi sub!"
child writes "hi dad!"
parent reads "hi dad!"

if the parent just exits after sending "hi sub!", the child will get an
error when replying (I think it says "invalid handle" on Windows, "broken
pipe" on Linux, or something like this).

--
Gabriel Genellina

Gabriel Genellina

unread,
Dec 15, 2008, 7:08:18 PM12/15/08
to pytho...@python.org
En Sun, 14 Dec 2008 06:03:26 -0200, greg <gr...@cosc.canterbury.ac.nz>
escribió:

But not on Linux; a visible difference is that pipes are half-duplex on
Linux (it seems that's enough for POSIX). I don't know for sure how
they're implemented on Windows but they seem to be file system objects
(they use functions like CreateFile, ReadFile, WriteFile, etc.)

--
Gabriel Genellina

0 new messages