Interacting with external program -pty?
Michael P. Reilly
arcege at shore.net
Wed Jan 19 12:51:27 EST 2000
Niklas.Blomberg at hassle.se.astra.com wrote:
: Dear all,
: I would appreciate some advice on how to script an external interactive
: process(program) using python. In addition to sending commands (which is
: straightforward) I need to be able to capture the output (which can be
: extensive) for further downstream processing. Since the program expects a
: terminal pipes don't work - the output is buffered - I have started to look
: at the pty module. This is uncharted territory for me and any advice both on
: possible solutions and perhaps availiable example code would be most
: appreciated.
: I'll be happy to post a summary.
There are a number of techniques you can use:
1) standard library module "pty"
>>> import os, pty
>>> master_fd, master_pty = pty.master_open()
>>> slave_fd = pty.slave_open(master_pty)
>>> os.write(master_fd, "hello\n")
6
>>> os.read(slave_fd, 6)
'hello\012'
>>> os.close(master_fd)
>>> os.close(slave_fd)
This needs to be wrapped with other code; there is a specialized
"fork" function in the method.
2) the ExpectPy module (<URL: http://starship.python.net/~arcege/>)
>>> import ExpectPy
>>> spawn_id = Expectpy.spawn('/bin/cat', 'cat')
>>> spawn_id.send('hello\r\n')
>>> spawn_id.expect((ExpectPy.GLOB, "*\n", None))
>>> spawn_id.match
'hello\015\012hello\015\012'
>>> spawn_id.close()
The message prints twice because it would in /bin/cat at the
terminal (cf. half versus full duplex).
3) depending on what you want: the standard library module "telnetlib"
This module is to be used to interact with a telnet session (not
with the telnet program).
4) fork, create pipes and exec
This is the low-level stuff.
>>> import os
>>> def myspawn(*args):
... (cld_reader, par_writer) = os.pipe()
... (par_reader, cld_writer) = os.pipe()
... pid = os.fork()
... if pid: # parent
... os.close(cld_reader)
... os.close(cld_writer)
... else: # child
... os.close(0); os.dup(cld_reader) # stdin
... os.close(1); os.dup(cld_writer) # stdout
... os.close(2); os.dup(cld_writer) # stderr
... os.close(cld_reader); os.close(par_writer)
... os.close(par_reader); os.close(cld_writer)
... os.execvp(args[0], args)
... os.exit(2) # if we canot exec()
... return (pid, (par_reader, par_writer))
...
>>> (pid, pipe) = myspawn('cat')
>>> os.write(pipe[1], 'hello\n')
>>> os.read(pipe[0], 6)
'hello\012'
>>> os.close(pipe[3])
>>> os.waitpid(pid, 0)
(82572, 2)
>>
Notice that the stderr goes the to same location as stdout, just
like pty's and terminals. This can be changed tho. ;)
I hope this helps.
-Arcege
More information about the Python-list
mailing list