popen problem

Noah noah at noah.org
Fri Mar 19 21:27:54 EST 2004


Gandalf <gandalf at geochemsource.com> wrote in message news:<mailman.79.1079528541.742.python-list at python.org>...
> I don't know if this is a Python problem or not. Here is a snippet:
> import os
> TERM='\n\r\n\r'
> cmd = 'cu -l /dev/cuaa0 -s9600'
> pop = os.popen4(cmd,1)
> pop[0].write('AT'+TERM) # Ping modem
>...
> 1. The first read blocks.
> 2. When I do 'killall cu' in another shell, it starts to read this:
> '\0x7Connected.'
> 'cu: Got interrupt signal'
> It seems that the first line ('Connected.') if buffered somewhere. I 
> guess 'OK' is also buffered but it is not read because of the interrup.
> Is it a problem with Linux of Python? Or is it a big difference between 
> /dev/ttyS0 and /dev/cuaa0?

Yes, it's buffer madness. This is a common problem with trying to use
a pipe with a child application that uses the stdio library -- which
is just about everything (does it #include <stdio.h>?) The annoying
thing is that it might seem to work sometimes, but then other times it
fails. Plus it's very platform dependent... When you kill the child
from another shell you are causing it to flush its buffer.
Unfortunately that's the only way that I know that you can force it to
flush the buffer -- not very practical.

Instead you should use my marvelous pexpect module.
    http://pexpect.sourceforge.net/
It's fun and educational and it's written in 100% pure, refreshing
Python, so it installs easily with no C extension hassles.

One of the features of the stdio library is that it buffers all input
and output. Normally output is line buffered when a program is
printing to a TTY (your terminal screen). Everytime the program prints
a line-feed the currently buffered data will get printed to your
screen. The problem comes when you connect a pipe. The stdio library
is smart and can tell that it is printing to a pipe instead of a TTY.
In that case it switches from line buffer mode to block buffered. In
this mode the currently buffered data is flushed when the BUFFER IS
FULL NOT WHEN THE CHILD PRINTS A LINE FEED. This causes most
interactive programs to deadlock. Block buffering is more efficient
when writing to disks and pipes. Take the situation where a program
prints a message "Enter your user name:\n" and then waits for you type
type something. In block buffered mode, the stdio library will not put
the message into the pipe even though a linefeed is printed. The
result is that you never receive the message, yet the child
application will sit and wait for you to type a response. Don't
confuse the stdio library buffer of the child with your pipe's buffer.
You could flush the your pipe, but that only flushes your output
stream, whereas you have no control over the stdio library buffer.

You can't force the child to flush it's stdout stream.
You can't force the child to change the buffer state to line
buffering.

Odd, but this is the second time today that I've seen this question
come up...

Yours,
Noah



More information about the Python-list mailing list