Newer
Older
pcl-expect
==========
pcl-expect is a pure-Python module written in the spirit of Don Libes'
expect program. There are already a number of expect modules for
Python available. (See the end of this file for a list of the ones I
know about.) This module has a few features that sets it apart:
- Full support for reading from several sources at once.
- Read input from a pty or stdin (like everybody other expect module
can), or from:
- a telnet connection
- a TCP connection
- a serial port (using the pySerial module)
- a program started via Peter Åstrands popen5 module (FIXME: not
- a program started in a pty, but with the stderr of the program
collected via a pipe so that you can differentiate between
stdout and stderr.
- Can spawn a program so that stdout is connected to a pty and stderr
to a pipe, so that you can see the difference between them.
- Support for expect_before and expect_after.
- Uses a syntax that is adapted to Python, to get more readable
code.
- Implemented in Python. No need to recompile a C module. Some
input methods requires non-standard Python modules to be installed,
but the other input methods can be used right away.
pcl-expect requires Python 2.3 or newer. The long-term goal is to add
pcl-expect to the core Python distribution, but it will live as a
standalone package for a while to prove that it is worthy.
You can investigate the demo subdirectory to find out how you can use
pcl-expect. These are probably the best demo programs to start
looking at:
- demo/microcom.py -- a minimal but working minicom/cu replacement: a
way to connect to a serial port.
- demo/ftp.py -- log on to ftp.funet.fi, cd to pub, and get a
directory listing.
- demo/ftp_interact.py -- log on to ftp.funet.fi, and let the user
give commands interactively. If the user enters "home", he
will be moved to the /pub/gnu/ftp.gnu.org/pub/gnu directory.
Feedback requested
==================
I want to know how much support pcl-expect has. I have set up three
email addresses that you can use to inform me about that you think.
Please send a mail to the appropriate address:
pcl-expect-now@ceder.user.lysator.liu.se
"Pcl-expect is ready for inclusion in the core Python
distribution. Please start the process of adding it there."
pcl-expect-notyet@ceder.user.lysator.liu.se
"Pcl-expect is a nice idea, but it is not yet mature enough to
add it to the core Python distribution." (Please use Bugzilla
to report any specific shortcomings.)
pcl-expect-never@ceder.user.lysator.liu.se
"Nice try, but... This should never be added to the Python
core."
I might read the mail sent to these addresses; I will count them.
Reporting bugs
==============
Please use the Bugzilla installation at
http://bugzilla.lysator.liu.se/
to report any bugs or feature requests. (If you also supply a patch,
you increase your chance of getting the bug fixed or feature added.)
If you are unable to use Bugzilla you can also reach the author at
<ceder+pcl-expect@lysator.liu.se>.
License
=======
Pcl-expect is currently distributed under the GNU General Public
License, version 2 (or, at your option, any later version). See
COPYING. If you need a less restrictive license, please contact me at
<ceder@lysator.liu.se>.
Alternatives to pcl-expect
==========================
Why write yet another expect module for Python? After all, there are
several others available. However, none of them are as good as
expect itself, and the design of them means that they cannot easily be
made as good. I felt that a fresh start was needed.
However, the alternatives are not all bad. They all have their strong
points, as this list will show. This list is sorted on release date,
with the most stale project first.
(If you are not interested in the competition to pcl-expect, you can
stop reading here.)
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
expy
----
Homepage: ftp://ftp.python.org/pub/python/contrib-09-Dec-1999/System
Review based on version: 0.4a
Release date: 1995-08-28
Authors: Saad Mufti and Farzad Farid
Uses Don Libes' expect library: yes
Uses Tkinter: no
Sample usage:
try:
val, spawn = expect.expect([([exp1, exp2], [(expect.glob, 'ftp> ', 1),
(expect.glob, 'Connection timeout', 2)])])
if val == 1:
spawn.send("Goober")
# Go On
elif val == 2:
spawn.send("Foo")
print 'Connection with the server timed out'
except expect.timeout
print 'We must be hung somewhere...'
Why this isn't good enough:
- no support for expect_after and expect_before
- cumbersome syntax
- needs TCL
Why this is better than the rest:
+ does support waiting for output from two processes at once. That
makes this the best expect integration into Python I've seen to
date.
pyexpect.py
-----------
Homepage:
ftp://ftp.sunsite.auc.dk/disk1/python/contrib-09-Dec-1999/System/pyexpect.py.Z
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
Review based on version: pyexpect.py,v 1.2 1996/10/07 23:41:48
Release date: 1996-10-07 (?)
Author: Mitchell S. Chapman
Uses Don Libes' expect library: no
Uses Tkinter: yes
Sample code:
patterns = ("OK", "NO", "BUSY", ".*[Bb]ye$")
status = apply(self.exp.expect, patterns)
if status >= 0:
print "Matched", patterns[status]
else:
print "Status =", status
Why this isn't good enough:
- there is no way to wait for input from more than one process at a
time.
- no support for expect_after and expect_before
- relies on a windows system!
Python-expect aka exploop.py
----------------------------
Homepage:
http://theopenlab.uml.edu/pipermail/loci-general/1999-April/000006.html
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
Review based on version: exploop.py,v 1.5 1997/01/27 19:11:59
Release date: 1997-01-27
Author: Tim O'Malley
Uses Don Libes' expect library: no
Uses Tkinter: no
Sample usage:
exp = Expect(sys.stdin, sys.stdout)
# Create our Patterns
pats = []
pats.append( Pattern(regex.compile("[Pp]ython"), _testCB) )
pats.append( Pattern(regex.compile("s+tar"), _testCB) )
# This pattern uses the default Pattern callback
pats.append( Pattern(regex.compile("[Bb]ye")))
# Output a prompt of sorts
exp.send("\nYou have 20 seconds. Type 'Bye' or 'bye' to exit sooner.\n")
# Call expect()...
try:
matcher = exp.expect(pats, 20)
print "\nGood Bye"
except ExpectTimeout:
print "\nTime has expired"
except ExpectEOF:
print "\nInput closed"
Why this isn't good enough:
- there is no way to wait for input from more than one process at a
time.
- no support for expect_after and expect_before
ExpectPy
--------
Homepage: http://expectpy.sourceforge.net/
Review based on version: 1.8.3
Release date: 2000-11-03
Author: Michael P. Reilly
Uses Don Libes' expect library: yes
Uses Tkinter: no
Sample usage:
spawn_id = ExpectPy.spawn('/bin/ed', 'ed', '/dev/null')
spawn_id.expect((ExpectPy.EXACT, "0\r\n", 0))
spawn_id.send('0a\rHello\r.\rw\r')
spawn_id.expect((ExpectPy.EXACT, '.\r\nw\r\n', 0))
rc = spawn_id.expect(
(ExpectPy.EXACT, '6\r\n', 1),
(ExpectPy.GLOB, '*\r\n', 2)
)
if rc == 1:
stdout.write('Test okay\n')
status = 1
elif rc == 2:
stdout.write('Test failed\n')
status = 0
Why this isn't good enough:
- there is no way to wait for input from more than one process at a
time.
- no support for expect_after and expect_before
- cumbersome syntax
- needs TCL
Pexpect
-------
Homepage: http://sourceforge.net/projects/pexpect/
Review based on version: 0.99
Release date: 2003-09-17
Author: Noah Spurrier
Uses Don Libes' expect library: no
Uses Tkinter: no
Sample usage:
child = pexpect.spawn('ssh -l %s %s'%(user, host))
i = child.expect([pexpect.TIMEOUT, SSH_NEWKEY, 'password: '])
if i == 0: # Timeout
print 'ERROR!'
print 'SSH could not login. Here is what SSH said:'
print child.before, child.after
sys.exit (1)
if i == 1: # SSH does not have the public key. Just accept it.
child.sendline ('yes')
child.expect ('password: ')
child.sendline(password)
Why this isn't good enough:
- there is no way to wait for input from more than one process at a
time.
- no support for expect_after and expect_before
However, this seems to have better pty support than any of the other
expect modules. It also have a screenscaping module that is probably
very useful if you want to write a program that interacts with a
curses-style program. If you only need to talk to one process at a
time, this seems to be a fairly mature and complete expect-like
module.
This is the only module that seems to be actively maintained.
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
telnetlib.py
------------
The telnetlib.py module supplied with Python contains an expect
method.
Sample usage:
tn = Telnet()
tn.open(host, port)
ix, match, txt = tn.expect(["login:"])
tn.write("ceder\n")
ix, match, txt = tn.expect(["password:", "ceder@.*>"])
if ix == 0:
tn.write("secret\n")
ix, match, txt = tn.expect(["ceder@.*>"])
Why this isn't good enough:
- only supports telnet
- there is no way to wait for input from more than one process at a
time.
- no support for expect_after and expect_before
- cumbersome syntax
Note: pcl_expect.telnet() uses telnetlib to implement telnet option
handling.
asynchat.py
-----------
The asynchat.py module supplied with Python contains "a class
supporting chat-style (command/response) protocols". Although this
has some similarities to what expect does, they really are two very
different things. asynchat.py can be used to build a system that
waits for input from serveral sources at once, and asyncore.py is
indeed a module that provides much of the necessary glue.
If you intend building "sophisticated high-performance network servers
and clients" you should probably use asyncore.py and asynchat.py. But
I think that there are many tasks where a more expect-like approach is
more appropriate.