[LONG] Custom debugger using popen.Popen3

Jonathan Gardner jgardn at alumni.washington.edu
Thu Feb 28 02:05:39 EST 2002


I am working on Linux 2.4.14 with Python 2.1.2.

Okay, I got popen.Popen3 working fine for standard python scripts. Example:
test.py=================
print "Oh yeah!"
END CODE=========

debug.py================
from select import select
from fcntl import fcntl
from FCNTL import F_SETFL, O_NONBLOCK
from popen2 import Popen3
from pprint import pformat

# Start the other process
dbg = Popen3("python test.py", 1)

# Non-blocking, please!
fcntl(dbg.fromchild.fileno(), F_SETFL, O_NONBLOCK)
fcntl(dbg.tochild.fileno(),   F_SETFL, O_NONBLOCK)
fcntl(dbg.childerr.fileno(),  F_SETFL, O_NONBLOCK)

# Process input
while 1:
    (r, w, e) = select([dbg.fromchild, ], [], [dbg.childerr, ], 1)
    for i in r:
        fromdbg = dbg.fromchild.read()
        if fromdbg:
            print "Input: %s" % pformat(fromdbg)
    for i in e:
        fromdbg = dbg.childerr.read()
        if fromdbg:
            print "Error: %s" % pformat(fromdbg)
    retval = dbg.poll()
    if retval != -1:
        print "Finished with '%d'" % retval
        break
    else:
        print "Still alive..."
END CODE=========

And here's the finished product:
$ python debug.py
Input: 'Oh yeah!\n'
Finished with '0'
$

Pretty cool, huh? I am in the driver's seat with other processes with only 
this little bit of code. (Python RULEZ!)

Let's upgrade to the new version that starts the debugger.

Let's try it from Bash:
$ python /usr/local/lib/python2.1/pdb.py test.py
> /home/jgardn/projects/debug/<string>(0)?()
(Pdb) 

If I type "q<enter>", it will do this:
$ python /usr/local/lib/python2.1/pdb.py test.py
> /home/jgardn/projects/debug/<string>(0)?()
(Pdb) q
$

Humm, so let's emulate this with my script:
debug.py (v0.2)===========
from select import select
from fcntl import fcntl
from FCNTL import F_SETFL, O_NONBLOCK
from popen2 import Popen3
from pprint import pformat

# Start the other process
dbg = Popen3("python /usr/local/lib/python2.1/pdb.py test.py", 1)

# Non-blocking, please!
fcntl(dbg.fromchild.fileno(), F_SETFL, O_NONBLOCK)
fcntl(dbg.tochild.fileno(),   F_SETFL, O_NONBLOCK)
fcntl(dbg.childerr.fileno(),  F_SETFL, O_NONBLOCK)

# Process input
sent_q = 0 # Whether or not I have told it to stop
while 1:
    w = []
    if not sent_q:
        w.append(dbg.tochild)
    (r, w, e) = select([dbg.fromchild, ], w, [dbg.childerr, ], 1)
    for i in r:
        fromdbg = dbg.fromchild.read()
        if fromdbg:
            print "Input: %s" % pformat(fromdbg)
    for i in e:
        fromdbg = dbg.childerr.read()
        if fromdbg:
            print "Error: %s" % pformat(fromdbg)
    for i in w:
        dbg.tochild.write('q\n')
        print "Wrote 'q\\n'"
        sent_q = 1
    retval = dbg.poll()
    if retval != -1:
        print "Finished with '%d'" % retval
        break
    else:
        print "Still alive..."
END CODE=========

The excitement is building... what will happen? Will it work? Will it not? 
LET'S FIND OUT!

$ python debug.py
Wrote 'q\n'
Still alive...
Still alive...
Still alive... (in 1 second intervals.)

Sure enough, the two processes are alive.

My question is this: How come? Why? Why doesn't the debugger print anything 
out to stdout? Is it "readline" that is screwing this up? Why would 
readline screw it up? It doesn't make any sense... any help would be 
greatly appreciated.

If I can't get this figured out, I will probably have to write a server 
that is based off of bdb and have the client connect to it...

Jonathan




More information about the Python-list mailing list