History¶
Releases¶
Version 4.8¶
Returned behavior of searchwindowsize to that in 4.3 and earlier (searches are only done within the search window) (PR #579).
Fixed a bug truncating
before
attribute after a timeout (PR #579).Fixed a bug where a search could be less than
searchwindowsize
if it was increased between calls (PR #579).Minor test cleanups to improve portability (PR #580) (PR #581) (PR #582) (PR #583) (PR #584) (PR #585).
Disable chaining of timeout and EOF exceptions (:gphull:`606`).
Allow traceback included snippet length to be configured via
str_last_chars
rather than always 100 (PR #598).Python 3 warning added to interact.py (PR #537).
Several doc updates.
Version 4.7¶
The
pxssh.login()
method now no longer requires a username if an ssh config is provided and will raise an error if neither are provided. (PR #562).The
pxssh.login()
method now supports providing your ownssh
command via thecmd
parameter. (PR #528) (PR #563).pxssh
now supports theuse_poll
parameter which is passed intopexpect.spawn()
(PR #542).Minor bug fix with
ssh_config
. (PR #498).replwrap.run_command()
now has async support via anasync_
parameter. (PR #501).pexpect.spawn()
will now read additional bytes if able up to a buffer limit. (PR #304).
Version 4.6¶
The
pxssh.login()
method now supports anssh_config
parameter, which can be used to specify a file path to an SSH config file (PR #490).Improved compatability for the
crlf
parameter ofPopenSpawn
(PR #493)Fixed an issue in read timeout handling when using
spawn
andfdspawn
with theuse_poll
parameter (PR #492).
Version 4.5¶
spawn
andfdspawn
now have ause_poll
parameter. If this is True, they will useselect.poll()
instead ofselect.select()
.poll()
allows file descriptors above 1024, but it must be explicitly enabled due to compatibility concerns (PR #474).The
pxssh.login()
method has several new and changed options:The option
password_regex
allows changing the password prompt regex, for servers that includepassword:
in a banner before reaching a prompt (PR #468).login()
now allows for setting up SSH tunnels to be requested once logged in to the remote server. This option isssh_tunnels
(PR #473). The structure should be like this:{ 'local': ['2424:localhost:22'], # Local SSH tunnels 'remote': ['2525:localhost:22'], # Remote SSH tunnels 'dynamic': [8888], # Dynamic/SOCKS tunnels }
The option
spawn_local_ssh=False
allows subsequent logins from the remote session and treats the session as if it was local (PR #472).Setting
sync_original_prompt=False
will prevent changing the prompt to something unique, in case the remote server is sensitive to new lines at login (PR #468).If
ssh_key=True
is passed, the SSH client forces forwarding the authentication agent to the remote server instead of providing a key (PR #473).
Version 4.4¶
PopenSpawn
now has apreexec_fn
parameter, likespawn
andsubprocess.Popen
, for a function to be called in the child process before executing the new command. Like inPopen
, this works only in POSIX, and can cause issues if your application also uses threads (PR #460).Significant performance improvements when processing large amounts of data (PR #464).
Ensure that
spawn.closed
gets set byclose()
, and improve an example for passingSIGWINCH
through to a child process (PR #466).
Version 4.3.1¶
When launching bash for
pexpect.replwrap
, load the systembashrc
from a couple of different common locations (PR #457), and then unset thePROMPT_COMMAND
environment variable, which can interfere with the prompt we’re expecting (PR #459).
Version 4.3¶
The
async=
parameter to integrate with asyncio has becomeasync_=
(PR #431), as async is becoming a Python keyword from Python 3.6. Pexpect will still recogniseasync
as an alternative spelling.Similarly, the module
pexpect.async
becamepexpect._async
(PR #450). This module is not part of the public API.Fix problems with asyncio objects closing file descriptors during garbage collection (#347, PR #376).
Set the
.pid
attribute of aPopenSpawn
object (PR #417).Fix passing Windows paths to
PopenSpawn
(PR #446).PopenSpawn
on Windows can pass string commands through toPopen
without splitting them into a list (PR #447).Stop
shlex
trying to read from stdin whenPopenSpawn
is passedcmd=None
(#433, PR #434).Ensure that an error closing a Pexpect spawn object raises a Pexpect error, rather than a Ptyprocess error (#383, PR #386).
Cleaned up invalid backslash escape sequences in strings (PR #430, PR #445).
The pattern for a password prompt in
pexpect.pxssh
changed frompassword
topassword:
(PR #452).Correct docstring for using unicode with spawn (PR #395).
Various other improvements to documentation.
Version 4.2.1¶
Fix to allow running
env
in replwrap-ed bash.Raise more informative exception from pxssh if it fails to connect.
Change
passmass
example to not log passwords entered.
Version 4.2¶
Change: When an
env
parameter is specified to thespawn
orrun
family of calls containing a value forPATH
, its value is used to discover the target executable from a relative path, rather than the current process’s environmentPATH
. This mirrors the behavior ofsubprocess.Popen()
in the standard library (#348).Regression: Re-introduce capability for
read_nonblocking()
in classfdspawn
as previously supported in version 3.3 (#359).
Version 4.0¶
Integration with
asyncio
: passingasync=True
toexpect()
,expect_exact()
orexpect_list()
will make them return a coroutine. You can get the result usingyield from
, or wrap it in anasyncio.Task
. This allows the event loop to do other things while waiting for output that matches a pattern.Experimental support for Windows (with some caveats)—see Pexpect on Windows.
Enhancement: allow method as callbacks of argument
events
forpexpect.run()
(#176).It is now possible to call
wait()
multiple times, or after a process is already determined to be terminated without raising an exception (PR #211).New
pexpect.spawn
keyword argument,dimensions=(rows, columns)
allows setting terminal screen dimensions before launching a program (#122).Fix regression that prevented executable, but unreadable files from being found when not specified by absolute path – such as /usr/bin/sudo (#104).
Fixed regression when executing pexpect with some prior releases of the multiprocessing module where stdin has been closed (#86).
Backwards incompatible changes¶
Deprecated
pexpect.screen
andpexpect.ANSI
. Please use other packages such as pyte to emulate a terminal.Removed the independent top-level modules (
pxssh fdpexpect FSM screen ANSI
) which were installed alongside Pexpect. These were moved into the Pexpect package in 3.0, but the old names were left as aliases.Child processes created by Pexpect no longer ignore SIGHUP by default: the
ignore_sighup
parameter ofpexpect.spawn
defaults to False. To get the old behaviour, passignore_sighup=True
.
Version 3.3¶
Added a mechanism to wrap REPLs, or shells, in an object which can conveniently be used to send commands and wait for the output (
pexpect.replwrap
).Fixed issue where pexpect would attempt to execute a directory because it has the ‘execute’ bit set (#37).
Removed the
pexpect.psh
module. This was never documented, and we found no evidence that people use it. The newpexpect.replwrap
module provides a more flexible alternative.Fixed
TypeError: got <type 'str'> ('\r\n') as pattern
inspawnu.readline()
method (#67).Fixed issue where EOF was not correctly detected in
interact()
, causing a repeating loop of output on Linux, and blocking before EOF on BSD and Solaris (#49).Several Solaris (SmartOS) bugfixes, preventing
IOError
exceptions, especially when used with cron(1) (#44).Added new keyword argument
echo=True
forspawn
. On SVR4-like systems, the methodisatty()
will always return False: the child pty does not appear as a terminal. Therefore,setecho()
,getwinsize()
,setwinsize()
, andwaitnoecho()
are not supported on those platforms.
After this, we intend to start working on a bigger refactoring of the code, to be released as Pexpect 4. There may be more bugfix 3.x releases, however.
Version 3.2¶
Fix exception handling from
select.select()
on Python 2 (PR #38). This was accidentally broken in the previous release when it was fixed for Python 3.Removed a workaround for
TIOCSWINSZ
on very old systems, which was causing issues on some BSD systems (PR #40).
The documentation for pxssh
was improved.
Version 3.1¶
Fix an issue that prevented importing pexpect on Python 3 when
sys.stdout
was reassigned (#30).Fix pickling exception instances (PR #34).
Fix handling exceptions from
select.select()
on Python 3 (PR #33).
The examples have also been cleaned up somewhat - this will continue in future releases.
Version 3.0¶
The new major version number doesn’t indicate any deliberate API incompatibility. We have endeavoured to avoid breaking existing APIs. However, pexpect is under new maintenance after a long dormancy, so some caution is warranted.
A new unicode API was introduced.
Python 3 is now supported, using a single codebase.
Pexpect now requires at least Python 2.6 or 3.2.
The modules other than pexpect, such as
pexpect.fdpexpect
andpexpect.pxssh
, were moved into the pexpect package. For now, wrapper modules are installed to the old locations for backwards compatibility (e.g.import pxssh
will still work), but these will be removed at some point in the future.Ignoring
SIGHUP
is now optional - thanks to Kimmo Parviainen-Jalanko for the patch.
We also now have docs on ReadTheDocs, and continuous integration on Travis CI.
Version 2.4¶
Fix a bug regarding making the pty the controlling terminal when the process spawning it is not, actually, a terminal (such as from cron)
Version 2.3¶
Fixed OSError exception when a pexpect object is cleaned up. Previously, you might have seen this exception:
Exception exceptions.OSError: (10, 'No child processes') in <bound method spawn.__del__ of <pexpect.spawn instance at 0xd248c>> ignored
You should not see that anymore. Thanks to Michael Surette.
Added support for buffering reads. This greatly improves speed when trying to match long output from a child process. When you create an instance of the spawn object you can then set a buffer size. For now you MUST do the following to turn on buffering – it may be on by default in future version:
child = pexpect.spawn ('my_command') child.maxread=1000 # Sets buffer to 1000 characters.
I made a subtle change to the way TIMEOUT and EOF exceptions behave. Previously you could either expect these states in which case pexpect will not raise an exception, or you could just let pexpect raise an exception when these states were encountered. If you expected the states then the
before
property was set to everything before the state was encountered, but if you let pexpect raise the exception thenbefore
was not set. Now, thebefore
property will get set either way you choose to handle these states.The spawn object now provides iterators for a file-like interface. This makes Pexpect a more complete file-like object. You can now write code like this:
child = pexpect.spawn ('ls -l') for line in child: print line
write and writelines() no longer return a value. Use send() if you need that functionality. I did this to make the Spawn object more closely match a file-like object.
Added the attribute
exitstatus
. This will give the exit code returned by the child process. This will be set toNone
while the child is still alive. Whenisalive()
returns 0 thenexitstatus
will be set.Made a few more tweaks to
isalive()
so that it will operate more consistently on different platforms. Solaris is the most difficult to support.You can now put
TIMEOUT
in a list of expected patterns. This is just like puttingEOF
in the pattern list. Expecting for aTIMEOUT
may not be used as often asEOF
, but this makes Pexpect more consistent.Thanks to a suggestion and sample code from Chad J. Schroeder I added the ability for Pexpect to operate on a file descriptor that is already open. This means that Pexpect can be used to control streams such as those from serial port devices. Now, you just pass the integer file descriptor as the “command” when constructing a spawn open. For example on a Linux box with a modem on ttyS1:
fd = os.open("/dev/ttyS1", os.O_RDWR|os.O_NONBLOCK|os.O_NOCTTY) m = pexpect.spawn(fd) # Note integer fd is used instead of usual string. m.send("+++") # Escape sequence m.send("ATZ0\r") # Reset modem to profile 0 rval = m.expect(["OK", "ERROR"])
read()
was renamed toread_nonblocking()
. Added newread()
method that matches file-like object interface. In general, you should not notice the difference except thatread()
no longer allows you to directly set the timeout value. I hope this will not effect any existing code. Switching toread_nonblocking()
should fix existing code.Changed the name of
set_echo()
tosetecho()
.Changed the name of
send_eof()
tosendeof()
.Modified
kill()
so that it checks to make sure the pidisalive()
.modified
spawn()
(really called from__spawn()
) so that it does not raise an exception ifsetwinsize()
fails. Some platforms such as Cygwin do not like setwinsize. This was a constant problem and since it is not a critical feature I decided to just silence the error. Normally I don’t like to do that, but in this case I’m making an exception.Added a method
close()
that does what you think. It closes the file descriptor of the child application. It makes no attempt to actually kill the child or wait for its status.Add variables
__version__
and__revision__
(from cvs) to the pexpect modules. This is mainly helpful to me so that I can make sure that I’m testing with the right version instead of one already installed.log_open()
andlog_close(
have been removed. Now usesetlog()
. Thesetlog()
method takes a file object. This is far more flexible than the previous log method. Each time data is written to the file object it will be flushed. To turn logging off simply callsetlog()
with None.renamed the
isAlive()
method toisalive()
to match the more typical naming style in Python. Also the technique used to detect child process status has been drastically modified. Previously I did some funky stuff with signals which caused indigestion in other Python modules on some platforms. It was a big headache. It still is, but I think it works better now.attribute
matched
renamed toafter
new attribute
match
The
expect_eof()
method is gone. You can now simply use theexpect()
method to look for EOF.Pexpect works on OS X, but the nature of the quirks cause many of the tests to fail. See bugs. (Incomplete Child Output). The problem is more than minor, but Pexpect is still more than useful for most tasks.
Solaris: For some reason, the second time a pty file descriptor is created and deleted it never gets returned for use. It does not effect the first time or the third time or any time after that. It’s only the second time. This is weird… This could be a file descriptor leak, or it could be some peculiarity of how Solaris recycles them. I thought it was a UNIX requirement for the OS to give you the lowest available filedescriptor number. In any case, this should not be a problem unless you create hundreds of pexpect instances… It may also be a pty module bug.
Moves and forks¶
Pexpect development used to be hosted on Sourceforge.
In 2011, Thomas Kluyver forked pexpect as ‘pexpect-u’, to support Python 3. He later decided he had taken the wrong approach with this.
In 2012, Noah Spurrier, the original author of Pexpect, moved the project to Github, but was still too busy to develop it much.
In 2013, Thomas Kluyver and Jeff Quast forked Pexpect again, intending to call the new fork Pexpected. Noah Spurrier agreed to let them use the name Pexpect, so Pexpect versions 3 and above are based on this fork, which now lives here on Github.