File: README

package info (click to toggle)
python-expect 1.0.5-2
  • links: PTS
  • area: main
  • in suites: woody
  • size: 320 kB
  • ctags: 122
  • sloc: ansic: 1,206; sh: 468; python: 157; makefile: 58
file content (306 lines) | stat: -rw-r--r-- 8,424 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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
159
160
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
189
190
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
305
306

Contents:
---------

* Contents:
* Expect Module for Python
* FTP:
* Example:
* Classes:
* How it works:
* Invocation:
* Methods:
* Backquote notation:
* Intricacies:
* Reading regular expressions:


Expect Module for Python
------------------------

This is Python module that does most of what you would normally
need from Tcl's expect, but it works like a standard popen(1)
call but with BOTH reading AND writing.


Example:
--------

    #!/usr/bin/python

    import sys
    from expect import *

    f = popen2 ("passwd " + sys.argv[1])
    print f.read ("word: ")
    f.write (sys.argv[2])
    print f.read ("word: ")
    f.write (sys.argv[2])
    print f.read ()

or

    #!/usr/bin/python

    import sys, time
    from expect import *

    f = popen2 ("passwd " + sys.argv[1], "p")
    print f.read (": ")
    time.sleep (0.1)
    f.write (sys.argv[2] + "\r\n")
    print f.read (":")
    time.sleep (0.1)
    f.write (sys.argv[2] + "\r\n")
    print f.read()


Classes:
--------

There are three classes defined by this module:
    popen - this is like a standard UNIX popen command
	    the difference being that you can both read
	    and write to the result file object. The stderr
	    stream of the process is NOT redirected and
	    will hence appear on the terminal exactly like
	    with popen or back-quotes under sh.

    popen2 - like popen, but both stderr AND stdout of the
	    process can be read through the same pipe. i.e.
	    f.read() calls return ALL output of the process.

    popen3 - like popen2, but stderr and stdout are read
	    through two separate functions: f.read()
	    returns stdout of the process. f.read_error()
	    returns stderr.


How it works:
-------------

This is a completely standalone implementation of popen. It does
not rely on the existing popen in any way.

The problem with reading and writing to a process is that it is
easy to write code that blocks indefinitely waiting for IO.

This library works by queueing reads when doing either a read or
a write call. Read operations are buffered so that incoming data
(the stderr and stdout of the process) are queued in
anticipation of any future read(). write() operations are
unbuffered.

This allows you to arbitrarily read to and write from a process
without worrying about an indefinite block. It is hence very
similar to Tcl's expect program.


Invocation:
-----------

f = popen (command, options)
f = popen2 (command, options)
f = popen3 (command, options)

command is a string. command is a shell program passed as <arg> to
    /bin/sh -c <arg>
options is a string. If options contains the character `b' then the
blocking is turned off. read() and write() will then not block waiting
for data. This is untested.

If options contains the character `p', then a pseudo tty is
opened for the process. The process will still inherit all
environment variables, hence for consistent behaviour, the
caller may want to explicitly set the TERM environment variable.
Note that many programs follow different behaviour depending on
whether they are attached to a tty or not.

In the passwd examples above, passwd is happy to read from a
pipe. If you use a terminal (`p') then you are required to send
a '\n' at the end of the line, and pause a small amount while
the getpass C library function switches into ICANON mode
(whatever that is) causing passwd to raw read separately from
the normal read queue.

All other letters passed to options are ignored.


Methods:
--------

f.read (integer)
    * Can take a normal integer to read a finite amount of data in the
	same way as usual file object's read does.

f.read ()
    * If no arguments are passed, then this reads as much data as is
	outputted by the process, blocking until it reads nothing
	(i.e. the process has exited).

f.read (string)
    * If a single string is passed, then read() reads up to and
	including the matching string.

f.read ((string, string, ...))
    * If a tuple of strings are passed, then read() reads up to and
	including the first matching string.

f.read_error ()
    * works just like read. Typically you would check for errors with
	read_error() after calling read().

f.close ()
    * closes all pipes and returns the exit code of the process. If
	the process has been killed, then this raises an error giving
	the terminating signal.

f.flush ()
    * does nothing

f.isatty ()
    * returns 0

f.readline ()
    * reads up to an including a newline character. takes no arguments

f.readlines ()
    * analogous to file objects readline(). takes no arguments

f.seek (offset, whence)
    * reads and discards offset amount of data. whence must be 1.
	returns nothing

f.tell ()
    * returns the total amount of data read from stdout (or in the case
	of popen2) from stdout and stderr.

f.writelines (list)
    * analogous to file objects writelines (). returns nothing.

f.pid ()
    * get the pid of the child process. Returns -1 if the child
	has died.

f.fds ()
    * get the stdin, stdout and stderr file descriptors as a tuple.

f.setblocking (block)
    * takes an integer. 1 turns blocking on, 0 turns blocking off.
	This overrides the options string. This is untested: rather
	use settimeout(). setblocking(0) takes priority over
	settimeout(anything).

f.settimeout (seconds)
    * takes a float. sets the timeout to this many seconds or
	fraction thereof. Tested only with reading but should work
	fine with writing. If a read waits longer than this
	for data, than it returns, raising an IO error. If timeout()
	receives no arguments, it resets to no timeout - i.e.
	indefinite blocking.

f.command
    * a copy of the command.


Backquote notation:
-------------------

Backquotes work the same as in sh. It does this by binding the
the __repr__ method. Hence

    a=`popen ("echo hello")`

Works just like

    a=`echo hello`

under a sh or perl.


Intricacies:
------------


- To avoid invocation of /bin/sh, popen checks if the command
    contains any shell special characters i.e.  > ` ! < & $ \n ;
    ( ) { }  and then, failing this, tries to interpret the
    command-line by itself, following the exact conventions of
    bash. If you are not convinced that this has the same behaviour,
    add in a ; at the end of your command to force use of /bin/sh.

- If you try to close a process that has stopped or still executing,
    close() will block waiting for the process to die.

- del f  is just like f.close(), but sends the process the
    SIGTERM signal before blocking waiting for the child to die.
    Since a process can intercept the SIGTERM signal, its is
    still possible for Python to block at an arbitrary location.
    For instance:

	def func ():
	    f = popen2 ("prog")
	    time.sleep (0.1)

	func ()

    If prog were to ignore SIGTERM, then func would block until
    prog had exited because python dereferences  f  before
    returning from func.

    (The reason you need to sleep(0.1) is to give prog a chance
    to set its signal handlers.)

    You can REALLY kill a program by getting it is pid and
    sending it the SIGKILL signal.

- f.p is the internal object that you would normally not be
    interested in. However `f.p` prints useful output like:

	f = popen2 ("echo 'Hi there!'")
	print `f.p`
	<ExpectObject running command "echo 'Hi there!'" as
		pid 10373 at 80b30c0>

- You can carry on reading from a process even after it has
    died and been close()'d. So long as there is still data
    in the queue. If there is no data, read just returns an
    empty string.

- Opening a pty currently works BSD style using /dev/pty??
    To support other kinds, I'll probably copy some of the
    rxvt code across. At the moment it works under Solaris
    and Linux, (and I assume all BSD variants).


Reading regular expressions:
----------------------------

Reading of regular expressions is not implemented in C, but
can be easily implemented in Python. Simply write a function
which reads up until the last character of a regular expression
and then compares the found data against it.

Please feel free to send a method which implements this for
inclusion into the distribution.

For instance:

    ...
    s = f.read ("(this|that|sh[aeiou]*p)")
    ...

	------->

    ...
    # this is off the top of my head: i.e. untested
    s = ""
    p = re.compile ("(this|that|sh[aeiou]*p)")
    while 1:
	s = s + f.read (("s", "t", "p"))
	if p.match (s)
	    break
    ...