472,958 Members | 2,328 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,958 software developers and data experts.

Bug/Weak Implementation? popen* routines can't handle simultaneous read/write?

Hi folks,

I've seen the following issue come up in multiple posts to this
mailing list:

I have a python program that spawns a child process with popen or
popen2 or popen3 or popen2.popen2 etc.
the child process is interactive: it asks for input then spits out
some output, asks for more input then spits out some output. for
example, consider the trivial child program:

print "welcome"
print ">",
s=raw_input()
while s!='exit':
print "you entered:",s
print ">",
s=raw_input()

Now I may be completely wrong about this (I did play with popen for a
very long time before writing this message), but it appears that none
of the popen variants allow for a sequence of reads and writes to/from
this child. that is, if I read from the open pipe's output I will
never be able to write the input for the child because the parent
program will block on read until eof (I will have similar blocking
problems if I start with write - using readline does not seem to
help).

the standard proposed remedy I have seen on this list is to use Unix-
only select/fctl, or otherwise dig into the bowls of the win32 api, or
download some half-complete sourceforge process control project. All
well and good, but unsatisfying for writing platform independent code.

it turns out that there is at least one open source multi-platform
(read: win32/linux) api that does handle synchronous I/O with the
child: wxWidgets and wxPython using the class wxProcess. Now the
wxWidgets implementation is far from perfect, but it at least allows a
program to test for new input on the child's stdout and read stdout/
write stdout in a non-blocking way. However, I find it frustrating
that I have to import wx just to have useable interactive pipes in my
python scripts when I would expect this to be part of the native
python implementation.

Anybody have any thoughts on this? Do I have my story straight? (the
popen variants can't handle this case and there are no other
alternatives in the standard python distro) Is there some place I can
submit this as a feature request? (Python dev?)

Jun 7 '07 #1
8 2836
dmoore <da**********@gmail.comwrote:
I've seen the following issue come up in multiple posts to this
mailing list:

I have a python program that spawns a child process with popen or
popen2 or popen3 or popen2.popen2 etc.
the child process is interactive: it asks for input then spits out
some output, asks for more input then spits out some output. for
example, consider the trivial child program:

print "welcome"
print ">",
s=raw_input()
while s!='exit':
print "you entered:",s
print ">",
s=raw_input()

Now I may be completely wrong about this (I did play with popen for a
very long time before writing this message), but it appears that none
of the popen variants allow for a sequence of reads and writes to/from
this child. that is, if I read from the open pipe's output I will
never be able to write the input for the child because the parent
program will block on read until eof (I will have similar blocking
problems if I start with write - using readline does not seem to
help).
You are correct.
the standard proposed remedy I have seen on this list is to use Unix-
only select/fctl, or otherwise dig into the bowls of the win32 api, or
download some half-complete sourceforge process control project.
If you are referring to pexpect I've found it works well - unix only
though. I've not noticed it being half complete.

There is also a recipe for a non-blocking subprocess - see

http://aspn.activestate.com/ASPN/Coo.../Recipe/440554
All well and good, but unsatisfying for writing platform independent code.

it turns out that there is at least one open source multi-platform
(read: win32/linux) api that does handle synchronous I/O with the
child: wxWidgets and wxPython using the class wxProcess. Now the
wxWidgets implementation is far from perfect, but it at least allows a
program to test for new input on the child's stdout and read stdout/
write stdout in a non-blocking way.
Interesting I didn't know about that - I shall try it!
However, I find it frustrating
that I have to import wx just to have useable interactive pipes in my
python scripts when I would expect this to be part of the native
python implementation.

Anybody have any thoughts on this? Do I have my story straight? (the
popen variants can't handle this case and there are no other
alternatives in the standard python distro) Is there some place I can
submit this as a feature request? (Python dev?)
The non-blocking subprocess would make a good start for a stdlib
submission.

It should really optionally use ptys under unix too otherwise you'll
never be able to script passwd etc. An interface a bit like pexpect
wpuld be useful too (ie scan for these regexps or timeout and return a
match object).

--
Nick Craig-Wood <ni**@craig-wood.com-- http://www.craig-wood.com/nick
Jun 7 '07 #2

"dmoore" <da**********@gmail.comwrote in message
news:11**********************@w5g2000hsg.googlegro ups.com...
| alternatives in the standard python distro) Is there some place I can
| submit this as a feature request? (Python dev?)

http://sourceforge.net/tracker/?group_id=5470

But don't hold your breath for a volunteer to respond. Discussion here is
good until you have a concrete request and support/rationale.


Jun 7 '07 #3
On Jun 7, 9:01 am, dmoore <damienlmo...@gmail.comwrote:

popen and friends will never do what you want it to do. Down that path
lies bitter disappointment.
You need pseduo-ttys and non-blocking IO. I don't know how to do this
on Windows, but I know it's possible.
Cygwin does it.
Anybody have any thoughts on this? Do I have my story straight? (the
popen variants can't handle this case and there are no other
alternatives in the standard python distro) Is there some place I can
submit this as a feature request? (Python dev?)
Try Pexpect http://pexpect.sourceforge.net/
It's been around for a long time and is quite complete and stable.

The catch is that it's UNIX-only. If you want to tease out the magic
code from wxProcess that
does non-blocking reads on win32 then I'd be happy to integrate that
into the current development branch
of Pexpect. If someone can provide a pure Python drop-in replacement
for the read_nonblocking() function
I use for UNIX systems then it would be easy. I have a whole test
framework that I can run it through to
see if it performs the same as the UNIX flavor.

I'm sure this is feasible without any C extensions -- it might require
some ctypes hacking.
I know Windows has pretty decent async IO, but I don't know what they
have as an equivalent for a pty.
Maybe it isn't necessary. A pty is only necessary on UNIX because the
standard c library, stdio, behaves
differently when it's talking to a plain pipe versus a terminal -- it
switches buffering
between block and line oriented buffer. You don't want block buffering
on interactive applications.
This is why popen eventually breaks down. No, there is no way to
select this behavior from
the calling side... unless you can trick it into dynamically linking
to your specially hacked libc.
But that's getting ahead because that's what happens on UNIX -- it
might be a non-issue on Windows.

The read_nonblocking() function I use has an interface like this:
<pre>
def read_nonblocking (self, size = 1, timeout = -1):

"""This reads at most size characters from the child
application. It
includes a timeout. If the read does not complete within the
timeout
period then a TIMEOUT exception is raised. If the end of file
is read
then an EOF exception will be raised. If a log file was set
using
setlog() then all data will also be written to the log file.

If timeout is None then the read may block indefinitely. If
timeout is -1
then the self.timeout value is used. If timeout is 0 then the
child is
polled and if there was no data immediately ready then this
will raise
a TIMEOUT exception.

The timeout refers only to the amount of time to read at least
one
character. This is not effected by the 'size' parameter, so if
you call
read_nonblocking(size=100, timeout=30) and only one character
is
available right away then one character will be returned
immediately.
It will not wait for 30 seconds for another 99 characters to
come in.

This is a wrapper around os.read(). It uses select.select() to
implement the timeout. """
</pre>

Yours,
Noah

Jun 8 '07 #4
thanks for all of your responses. i'll look more closely at pexpect
(The version I originally saw was much much older). I do want a cross-
platform solution. I'm pretty busy so getting the wxProcess magic into
useful shape will take me some time (at least on the order of weeks)
so other interest parties feel free to step up.

cheers
Damien

On Jun 7, 8:59 pm, Noah <n...@noah.orgwrote:
On Jun 7, 9:01 am, dmoore <damienlmo...@gmail.comwrote:

popen and friends will never do what you want it to do. Down that path
lies bitter disappointment.
You need pseduo-ttys and non-blocking IO. I don't know how to do this
on Windows, but I know it's possible.
Cygwin does it.
Anybody have any thoughts on this? Do I have my story straight? (the
popen variants can't handle this case and there are no other
alternatives in the standard python distro) Is there some place I can
submit this as a feature request? (Python dev?)

Try Pexpecthttp://pexpect.sourceforge.net/
It's been around for a long time and is quite complete and stable.

The catch is that it's UNIX-only. If you want to tease out the magic
code from wxProcess that
does non-blocking reads on win32 then I'd be happy to integrate that
into the current development branch
of Pexpect. If someone can provide a pure Python drop-in replacement
for the read_nonblocking() function
I use for UNIX systems then it would be easy. I have a whole test
framework that I can run it through to
see if it performs the same as the UNIX flavor.

I'm sure this is feasible without any C extensions -- it might require
some ctypes hacking.
I know Windows has pretty decent async IO, but I don't know what they
have as an equivalent for a pty.
Maybe it isn't necessary. A pty is only necessary on UNIX because the
standard c library, stdio, behaves
differently when it's talking to a plain pipe versus a terminal -- it
switches buffering
between block and line oriented buffer. You don't want block buffering
on interactive applications.
This is why popen eventually breaks down. No, there is no way to
select this behavior from
the calling side... unless you can trick it into dynamically linking
to your specially hacked libc.
But that's getting ahead because that's what happens on UNIX -- it
might be a non-issue on Windows.

The read_nonblocking() function I use has an interface like this:
<pre>
def read_nonblocking (self, size = 1, timeout = -1):

"""This reads at most size characters from the child
application. It
includes a timeout. If the read does not complete within the
timeout
period then a TIMEOUT exception is raised. If the end of file
is read
then an EOF exception will be raised. If a log file was set
using
setlog() then all data will also be written to the log file.

If timeout is None then the read may block indefinitely. If
timeout is -1
then the self.timeout value is used. If timeout is 0 then the
child is
polled and if there was no data immediately ready then this
will raise
a TIMEOUT exception.

The timeout refers only to the amount of time to read at least
one
character. This is not effected by the 'size' parameter, so if
you call
read_nonblocking(size=100, timeout=30) and only one character
is
available right away then one character will be returned
immediately.
It will not wait for 30 seconds for another 99 characters to
come in.

This is a wrapper around os.read(). It uses select.select() to
implement the timeout. """
</pre>

Yours,
Noah

Jun 8 '07 #5
"dmoore" <da..e@gmail.comwrote:

8< --------------- <description of full duplex problem------------
Anybody have any thoughts on this? Do I have my story straight? (the
popen variants can't handle this case and there are no other
alternatives in the standard python distro) Is there some place I can
submit this as a feature request? (Python dev?)
I think this is a hassle in the file implementation - I have had it also on
serial ports, where it acts as if the file "driver" is inherently half duplex.

It manifests as: "My characters don't come out"

I don't know if it is python or the underlying stuff.

I use fcntl to unblock and generally mess around to solve it, but
I don't think my solution is portable.

It is a real issue though - you are not imagining the dragon, it is
right at the door...

- Hendrik

Jun 8 '07 #6
Noah <no**@noah.orgwrote:
On Jun 7, 9:01 am, dmoore <damienlmo...@gmail.comwrote:

popen and friends will never do what you want it to do. Down that path
lies bitter disappointment.
You need pseduo-ttys and non-blocking IO. I don't know how to do this
on Windows, but I know it's possible.
Cygwin does it.
Anybody have any thoughts on this? Do I have my story straight? (the
popen variants can't handle this case and there are no other
alternatives in the standard python distro) Is there some place I can
submit this as a feature request? (Python dev?)

Try Pexpect http://pexpect.sourceforge.net/
It's been around for a long time and is quite complete and stable.

The catch is that it's UNIX-only. If you want to tease out the magic
code from wxProcess that
does non-blocking reads on win32 then I'd be happy to integrate that
into the current development branch
of Pexpect.
Windows has a really strange idea of non-blocking IO - it uses
something called overlapped io. You or in the FILE_FLAG_OVERLAPPED
flag when you create the file/pipe. You then pass in overlap buffers
for reading writing.

I implemented this for serial ports in C a while ago. If you look at
the code in pyserial (in serialwin32.py) you'll see a very similar
implementation of non blocking IO. I assume that the same things will
work for pipes, but I've only direct experience with serial ports!
I'm sure this is feasible without any C extensions -- it might require
some ctypes hacking.
pyserial uses win32file and win32event
I know Windows has pretty decent async IO, but I don't know what they
have as an equivalent for a pty.
Maybe it isn't necessary. A pty is only necessary on UNIX because the
standard c library, stdio, behaves
differently when it's talking to a plain pipe versus a terminal -- it
switches buffering
between block and line oriented buffer. You don't want block buffering
on interactive applications.
Pty's probably aren't needed on Windows.

BTW I'd love to see pexpect working on windows and also in the
standard library. It is the proper answer to controlling other
interactive processes IMHO.

--
Nick Craig-Wood <ni**@craig-wood.com-- http://www.craig-wood.com/nick
Jun 8 '07 #7
On Jun 8, 12:30 pm, Nick Craig-Wood <n...@craig-wood.comwrote:
Windows has a really strange idea of non-blocking IO - it uses
something called overlapped io. You or in the FILE_FLAG_OVERLAPPED
flag when you create the file/pipe. You then pass in overlap buffers
for reading writing.
the wx guys appear to do it differently (unless FILE_FLAG_OVERLAPPED
is implicit in the calls they make)

take a look at:
http://cvs.wxwidgets.org/viewcvs.cgi...viewcvs-markup

a reasonably well-documented wxExecute function handles all the messy
win32 api calls and wraps the process in a wxProcess object and the
streams in wxInputStream / wxOutputStream (also see the wxExecuteDDE
function)

Jun 8 '07 #8
dmoore <da**********@gmail.comwrote:
On Jun 8, 12:30 pm, Nick Craig-Wood <n...@craig-wood.comwrote:
Windows has a really strange idea of non-blocking IO - it uses
something called overlapped io. You or in the FILE_FLAG_OVERLAPPED
flag when you create the file/pipe. You then pass in overlap buffers
for reading writing.

the wx guys appear to do it differently (unless FILE_FLAG_OVERLAPPED
is implicit in the calls they make)

take a look at:
http://cvs.wxwidgets.org/viewcvs.cgi...viewcvs-markup

a reasonably well-documented wxExecute function handles all the messy
win32 api calls and wraps the process in a wxProcess object and the
streams in wxInputStream / wxOutputStream (also see the wxExecuteDDE
function)
You are right, named pipes seem to have a non blocking mode.

Here is the lowdown from
http://msdn2.microsoft.com/en-US/library/aa365605.aspx

Both pipe clients and pipe servers can change a pipe handle's wait
mode by specifying either PIPE_WAIT or PIPE_NOWAIT in a call to the
SetNamedPipeHandleState function.

Note The nonblocking-wait mode is supported for compatibility with
Microsoft® LAN Manager version 2.0. This mode should not be used to
achieve overlapped input and output (I/O) with named
pipes. Overlapped I/O should be used instead, because it enables
time-consuming operations to run in the background after the
function returns. For more information about overlapped I/O, see
Synchronous and Overlapped Input and Output.

So it has a nonblocking mode but you shouldn't use it!

--
Nick Craig-Wood <ni**@craig-wood.com-- http://www.craig-wood.com/nick
Jun 10 '07 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
by: JoshuaF | last post by:
hello everyone i am very new to postgresql 7.3.3 and am using it on my mac G4 OS X and i am having some trouble which i hope you can help me out with some answers to my questions: 1.) How can I...
17
by: bastiaannaber | last post by:
I am trying to write a program which uses popen but I have a problem. I want to detect if the program I call with popen has ended. For example: #include <stdio.h> #include <sys/types.h>...
12
by: Dan V. | last post by:
Since an ASP.NET/ADO.NET website is run on the server by a single "asp_net worker process", therefore doesn't that mean that even 50 simultaneous human users of the website would appear to the...
1
by: Rick Spencer | last post by:
Hi all, I am very new to Python programming. I am writing a program to manage wireless connections, this is for GNOME on Linux. I present the user with a "connect" button. I want to handle the...
2
by: Greg Ercolano | last post by:
When I use os.popen(cmd,'w'), I find that under windows, the stdout of the child process disappears, instead of appearing in the DOS window the script is invoked from. eg: C:\type foo.py import...
3
by: Jesse | last post by:
Hi all, I have a problem using wget and Popen. I hope someone can help. -- Problem -- I want to use the command: wget -nv -O "dir/cpan.txt" "http://search.cpan.org" and capture all it's...
1
by: WolfgangZ | last post by:
Hello, I'm starting some subprocesses inside a loop. The processes run independent and dont need any communication between each other. Due to memory issues I need to limit the number of running...
1
by: Henri.Chinasque | last post by:
Hi all, I've been considering that my objects should subscribe to an event via a weak reference, however I've found several warnings that this approach comes with concurrency considerations,...
5
by: thedsadude | last post by:
Hello, I'm launching a script as follows: <code> p = subprocess.Popen() p.wait() </code> If p.py writes to sys.stdout, then it is shown on the console.
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 4 Oct 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
by: Aliciasmith | last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
2
by: giovanniandrean | last post by:
The energy model is structured as follows and uses excel sheets to give input data: 1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
1
by: Teri B | last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course. 0ne-to-many. One course many roles. Then I created a report based on the Course form and...
0
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...
2
by: GKJR | last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.