469,323 Members | 1,560 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,323 developers. It's quick & easy.

popen problem


Hi All!

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

def readln():
buffer = ''
while True:
c = pop[1].read(1)
if c == '\n':
return buffer
elif (c != '\r') and not (c in TERM):
buffer += c

pop[1].readln()
pop[1].readln()
pop[1].readln()

Here is the problem: on FreeBSD, this works fine. The last readln()
calls will print this:

'Connected.'
''
'OK'

But if I try to do the same on Linux (with /dev/ttyS0 instead of
/dev/cuaa0) I get this:

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?

Thanks in advance,

G

Jul 18 '05 #1
2 3789
Gandalf wrote:

Hi All!

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)


You want to use a bufsize of 1? The Python docs say that bufsize is
the third param to popen4, does
pop = os.popen4(cmd,'t',0)
or pop = os.popen4(cmd, bufsize = 0)
a better job?

Mathias
Jul 18 '05 #2
Gandalf <ga*****@geochemsource.com> wrote in message news:<ma***********************************@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
Jul 18 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

9 posts views Thread by Bryan | last post: by
2 posts views Thread by Sami Viitanen | last post: by
1 post views Thread by sam | last post: by
17 posts views Thread by bastiaannaber | last post: by
1 post views Thread by rveloso | last post: by
2 posts views Thread by Maarten van Veen | last post: by
3 posts views Thread by Jesse | last post: by
12 posts views Thread by Eric_Dexter | last post: by
15 posts views Thread by Daniel Klein | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by Gurmeet2796 | last post: by
reply views Thread by mdpf | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.