[pygtk] Hi, all! I'm new to the list. How can I create please a frontend for a TUI command?

A.T.Hofkamp a.t.hofkamp at tue.nl
Wed Oct 29 21:12:01 WST 2008


Néstor Amigo Cairo wrote:
> Ok, now I have some more comments. I have tried it, and it works fine
> when the application sends output as newlines, but sometimes, it
> prints a line and then waits to put some more output before the
> newline, and then, the application locks up.
> For example:
> 
> # /sbin/badblocks --vw /dev/testdevice
> Checking for bad blocks in read-write mode
>>From block 0 to 1007496
> Testing with pattern 0xaa:
> 
> and then, Done is put on the end of the last line, and a newline is
> added. But a new IO_IN event is triggered just as the line starts to
> arrive, and readline() has to wait for the newline to arrive, while
> the application is locked.

Basically, the solution is: don't use 'readline()'.


A safe solution is to use source.read(1), which reads 1 character strings 
(which are garanteed to exist, otherwise gobject would not have triggered the 
event). In this way you will never block in the read() call.
(note that you may still get a 0 length string, indicating that you have read 
all data from the stream.)


Since you are reading partial lines in this way, you'll also have to handle 
partial lines in your event handler. You can collect the read 1 character 
strings into a longer string until you receive a \n, and then forward the read 
line into the widget, ie

data = source.read(1)
# check for len(data) == 0 and act on it
collected = collected + data
if collected[-1] == '\n':
     # collected is a complete line, do something with it
     collected = ""

Alternatively, you may be able to push the read bytes directly in the widget 
(I have no experience with TextView, so I cannot help you here).


The disadvantage of the above is that you read 1 character strings, which may 
be highly inefficient if you get large volumes of output to read.
An other solution is to use os.read(source.fileno(), 1024). os.read() reads as 
much data as available, upto (in this case) 1024 characters. That upper limit 
is kind of arbitrary, if you expect large amounts of output, you should 
increase it.
Here you'll read chunks of data (upto 1024 chars at a time), broken at 
arbitrary points in the output stream. It may be less than a line, it may be a 
line, it may be 5 lines and 10 characters, etc.
If you want to work line-based, the simplest solution is something like

chunk = os.read( ... )
# check for len(chunk) == 0 and act on it
collected = collected + chunk
i = collected.find('\n')
while i >= 0:
   line = collected[:i]
   collected = collected[i+1:]
   # do something with 'line'
   i = collected.find('\n')

Like above, if you don't care about lines, it may be easier (I never tried that).


Good luck,
Albert


More information about the pygtk mailing list