Interacting with external program -pty?

1 view
Skip to first unread message

Niklas....@hassle.se.astra.com

unread,
Jan 18, 2000, 3:00:00 AM1/18/00
to pytho...@python.org
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.

Thanks,
Niklas

-----
Niklas Blomberg
AstraZeneca Structural Chemistry Laboratory
niklas....@astrazeneca.com


Emile van Sebille

unread,
Jan 18, 2000, 3:00:00 AM1/18/00
to Niklas....@hassle.se.astra.com, pytho...@python.org
Niklas,

Look for expect.py on the net and at telnetlib.py in
the standard distribution.

HTH

Emile van Sebille
em...@fenx.com
-------------------

> --
> http://www.python.org/mailman/listinfo/python-list
>


Michael P. Reilly

unread,
Jan 19, 2000, 3:00:00 AM1/19/00
to
Niklas....@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


Reply all
Reply to author
Forward
0 new messages