OLD | NEW |
(Empty) | |
| 1 API Overview |
| 2 ============ |
| 3 |
| 4 Pexpect can be used for automating interactive applications such as ssh, ftp, |
| 5 mencoder, passwd, etc. The Pexpect interface was designed to be easy to use. |
| 6 |
| 7 Here is an example of Pexpect in action:: |
| 8 |
| 9 # This connects to the openbsd ftp site and |
| 10 # downloads the recursive directory listing. |
| 11 import pexpect |
| 12 child = pexpect.spawn('ftp ftp.openbsd.org') |
| 13 child.expect('Name .*: ') |
| 14 child.sendline('anonymous') |
| 15 child.expect('Password:') |
| 16 child.sendline('noah@example.com') |
| 17 child.expect('ftp> ') |
| 18 child.sendline('lcd /tmp') |
| 19 child.expect('ftp> ') |
| 20 child.sendline('cd pub/OpenBSD') |
| 21 child.expect('ftp> ') |
| 22 child.sendline('get README') |
| 23 child.expect('ftp> ') |
| 24 child.sendline('bye') |
| 25 |
| 26 Obviously you could write an ftp client using Python's own :mod:`ftplib` module, |
| 27 but this is just a demonstration. You can use this technique with any applicatio
n. |
| 28 This is especially handy if you are writing automated test tools. |
| 29 |
| 30 There are two important methods in Pexpect -- :meth:`~pexpect.spawn.expect` and |
| 31 :meth:`~pexpect.spawn.send` (or :meth:`~pexpect.spawn.sendline` which is |
| 32 like :meth:`~pexpect.spawn.send` with a linefeed). The :meth:`~pexpect.spawn.exp
ect` |
| 33 method waits for the child application to return a given string. The string you |
| 34 specify is a regular expression, so you can match complicated patterns. The |
| 35 :meth:`~pexpect.spawn.send` method writes a string to the child application. |
| 36 From the child's point of view it looks just like someone typed the text from a |
| 37 terminal. After each call to :meth:`~pexpect.spawn.expect` the ``before`` and ``
after`` |
| 38 properties will be set to the text printed by child application. The ``before`` |
| 39 property will contain all text up to the expected string pattern. The ``after`` |
| 40 string will contain the text that was matched by the expected pattern. |
| 41 The match property is set to the `re match object <http://docs.python.org/3/libr
ary/re#match-objects>`_. |
| 42 |
| 43 An example of Pexpect in action may make things more clear. This example uses |
| 44 ftp to login to the OpenBSD site; list files in a directory; and then pass |
| 45 interactive control of the ftp session to the human user:: |
| 46 |
| 47 import pexpect |
| 48 child = pexpect.spawn ('ftp ftp.openbsd.org') |
| 49 child.expect ('Name .*: ') |
| 50 child.sendline ('anonymous') |
| 51 child.expect ('Password:') |
| 52 child.sendline ('noah@example.com') |
| 53 child.expect ('ftp> ') |
| 54 child.sendline ('ls /pub/OpenBSD/') |
| 55 child.expect ('ftp> ') |
| 56 print child.before # Print the result of the ls command. |
| 57 child.interact() # Give control of the child to the user. |
| 58 |
| 59 Special EOF and TIMEOUT patterns |
| 60 -------------------------------- |
| 61 |
| 62 There are two special patterns to match the End Of File (:class:`~pexpect.EOF`) |
| 63 or a Timeout condition (:class:`~pexpect.TIMEOUT`). You can pass these |
| 64 patterns to :meth:`~pexpect.spawn.expect`. These patterns are not regular |
| 65 expressions. Use them like predefined constants. |
| 66 |
| 67 If the child has died and you have read all the child's output then ordinarily |
| 68 :meth:`~pexpect.spawn.expect` will raise an :class:`~pexpect.EOF` exception. |
| 69 You can read everything up to the EOF without generating an exception by using |
| 70 the EOF pattern expect. In this case everything the child has output will be |
| 71 available in the ``before`` property. |
| 72 |
| 73 The pattern given to :meth:`~pexpect.spawn.expect` may be a regular expression |
| 74 or it may also be a list of regular expressions. This allows you to match |
| 75 multiple optional responses. The :meth:`~pexpect.spawn.expect` method returns |
| 76 the index of the pattern that was matched. For example, say you wanted to login |
| 77 to a server. After entering a password you could get various responses from the |
| 78 server -- your password could be rejected; or you could be allowed in and asked |
| 79 for your terminal type; or you could be let right in and given a command prompt. |
| 80 The following code fragment gives an example of this:: |
| 81 |
| 82 child.expect('password:') |
| 83 child.sendline(my_secret_password) |
| 84 # We expect any of these three patterns... |
| 85 i = child.expect (['Permission denied', 'Terminal type', '[#\$] ']) |
| 86 if i==0: |
| 87 print('Permission denied on host. Can\'t login') |
| 88 child.kill(0) |
| 89 elif i==1: |
| 90 print('Login OK... need to send terminal type.') |
| 91 child.sendline('vt100') |
| 92 child.expect('[#\$] ') |
| 93 elif i==2: |
| 94 print('Login OK.') |
| 95 print('Shell command prompt', child.after) |
| 96 |
| 97 If nothing matches an expected pattern then :meth:`~pexpect.spawn.expect` will |
| 98 eventually raise a :class:`~pexpect.TIMEOUT` exception. The default time is 30 |
| 99 seconds, but you can change this by passing a timeout argument to |
| 100 :meth:`~pexpect.spawn.expect`:: |
| 101 |
| 102 # Wait no more than 2 minutes (120 seconds) for password prompt. |
| 103 child.expect('password:', timeout=120) |
| 104 |
| 105 Find the end of line -- CR/LF conventions |
| 106 ----------------------------------------- |
| 107 |
| 108 Pexpect matches regular expressions a little differently than what you might be |
| 109 used to. |
| 110 |
| 111 The :regexp:`$` pattern for end of line match is useless. The :regexp:`$` |
| 112 matches the end of string, but Pexpect reads from the child one character at a |
| 113 time, so each character looks like the end of a line. Pexpect can't do a |
| 114 look-ahead into the child's output stream. In general you would have this |
| 115 situation when using regular expressions with any stream. |
| 116 |
| 117 .. note:: |
| 118 |
| 119 Pexpect does have an internal buffer, so reads are faster than one character |
| 120 at a time, but from the user's perspective the regex patterns test happens |
| 121 one character at a time. |
| 122 |
| 123 The best way to match the end of a line is to look for the newline: ``"\r\n"`` |
| 124 (CR/LF). Yes, that does appear to be DOS-style. It may surprise some UNIX people |
| 125 to learn that terminal TTY device drivers (dumb, vt100, ANSI, xterm, etc.) all |
| 126 use the CR/LF combination to signify the end of line. Pexpect uses a Pseudo-TTY |
| 127 device to talk to the child application, so when the child app prints ``"\n"`` |
| 128 you actually see ``"\r\n"``. |
| 129 |
| 130 UNIX uses just linefeeds to end lines of text, but not when it comes to TTY |
| 131 devices! TTY devices are more like the Windows world. Each line of text ends |
| 132 with a CR/LF combination. When you intercept data from a UNIX command from a |
| 133 TTY device you will find that the TTY device outputs a CR/LF combination. A |
| 134 UNIX command may only write a linefeed (``\n``), but the TTY device driver |
| 135 converts it to CR/LF. This means that your terminal will see lines end with |
| 136 CR/LF (hex ``0D 0A``). Since Pexpect emulates a terminal, to match ends of |
| 137 lines you have to expect the CR/LF combination:: |
| 138 |
| 139 child.expect('\r\n') |
| 140 |
| 141 If you just need to skip past a new line then ``expect('\n')`` by itself will |
| 142 work, but if you are expecting a specific pattern before the end of line then |
| 143 you need to explicitly look for the ``\r``. For example the following expects a |
| 144 word at the end of a line:: |
| 145 |
| 146 child.expect('\w+\r\n') |
| 147 |
| 148 But the following would both fail:: |
| 149 |
| 150 child.expect('\w+\n') |
| 151 |
| 152 And as explained before, trying to use :regexp:`$` to match the end of line |
| 153 would not work either:: |
| 154 |
| 155 child.expect ('\w+$') |
| 156 |
| 157 So if you need to explicitly look for the END OF LINE, you want to look for the |
| 158 CR/LF combination -- not just the LF and not the $ pattern. |
| 159 |
| 160 This problem is not limited to Pexpect. This problem happens any time you try |
| 161 to perform a regular expression match on a stream. Regular expressions need to |
| 162 look ahead. With a stream it is hard to look ahead because the process |
| 163 generating the stream may not be finished. There is no way to know if the |
| 164 process has paused momentarily or is finished and waiting for you. Pexpect must |
| 165 implicitly always do a NON greedy match (minimal) at the end of a input. |
| 166 |
| 167 Pexpect compiles all regular expressions with the :data:`re.DOTALL` flag. |
| 168 With the :data:`~re.DOTALL` flag, a ``"."`` will match a newline. |
| 169 |
| 170 Beware of + and * at the end of patterns |
| 171 ---------------------------------------- |
| 172 |
| 173 Remember that any time you try to match a pattern that needs look-ahead that |
| 174 you will always get a minimal match (non greedy). For example, the following |
| 175 will always return just one character:: |
| 176 |
| 177 child.expect ('.+') |
| 178 |
| 179 This example will match successfully, but will always return no characters:: |
| 180 |
| 181 child.expect ('.*') |
| 182 |
| 183 Generally any star * expression will match as little as possible. |
| 184 |
| 185 One thing you can do is to try to force a non-ambiguous character at the end of |
| 186 your :regexp:`\\d+` pattern. Expect that character to delimit the string. For |
| 187 example, you might try making the end of your pattern be :regexp:`\\D+` instead |
| 188 of :regexp:`\\D*`. Number digits alone would not satisfy the :regexp:`(\\d+)\\D+
` |
| 189 pattern. You would need some numbers and at least one non-number at the end. |
| 190 |
| 191 |
| 192 Debugging |
| 193 --------- |
| 194 |
| 195 If you get the string value of a :class:`pexpect.spawn` object you will get lots |
| 196 of useful debugging information. For debugging it's very useful to use the |
| 197 following pattern:: |
| 198 |
| 199 try: |
| 200 i = child.expect ([pattern1, pattern2, pattern3, etc]) |
| 201 except: |
| 202 print("Exception was thrown") |
| 203 print("debug information:") |
| 204 print(str(child)) |
| 205 |
| 206 It is also useful to log the child's input and out to a file or the screen. The |
| 207 following will turn on logging and send output to stdout (the screen):: |
| 208 |
| 209 child = pexpect.spawn(foo) |
| 210 child.logfile = sys.stdout |
| 211 |
| 212 Exceptions |
| 213 ---------- |
| 214 |
| 215 :class:`~pexpect.EOF` |
| 216 |
| 217 Note that two flavors of EOF Exception may be thrown. They are virtually |
| 218 identical except for the message string. For practical purposes you should have |
| 219 no need to distinguish between them, but they do give a little extra information |
| 220 about what type of platform you are running. The two messages are: |
| 221 |
| 222 - "End Of File (EOF) in read(). Exception style platform." |
| 223 - "End Of File (EOF) in read(). Empty string style platform." |
| 224 |
| 225 Some UNIX platforms will throw an exception when you try to read from a file |
| 226 descriptor in the EOF state. Other UNIX platforms instead quietly return an |
| 227 empty string to indicate that the EOF state has been reached. |
| 228 |
| 229 If you wish to read up to the end of the child's output without generating an |
| 230 :class:`~pexpect.EOF` exception then use the ``expect(pexpect.EOF)`` method. |
| 231 |
| 232 :class:`~pexpect.TIMEOUT` |
| 233 |
| 234 The :meth:`~pexpect.spawn.expect` and :meth:`~pexpect.spawn.read` methods will |
| 235 also timeout if the child does not generate any output for a given amount of |
| 236 time. If this happens they will raise a :class:`~pexpect.TIMEOUT` exception. |
| 237 You can have these methods ignore timeout and block indefinitely by passing |
| 238 ``None`` for the timeout parameter:: |
| 239 |
| 240 child.expect(pexpect.EOF, timeout=None) |
| 241 |
| 242 .. _windows: |
| 243 |
| 244 Pexpect on Windows |
| 245 ------------------ |
| 246 |
| 247 .. versionadded:: 4.0 |
| 248 Windows support |
| 249 |
| 250 Pexpect can be used on Windows to wait for a pattern to be produced by a child |
| 251 process, using :class:`pexpect.popen_spawn.PopenSpawn`, or a file descriptor, |
| 252 using :class:`pexpect.fdpexpect.fdspawn`. This should be considered experimental |
| 253 for now. |
| 254 |
| 255 :class:`pexpect.spawn` and :func:`pexpect.run` are *not* available on Windows, |
| 256 as they rely on Unix pseudoterminals (ptys). Cross platform code must not use |
| 257 these. |
OLD | NEW |