Pure Python module for spawning child applications and controlling them automatically with expect-like functionality.
—
Powerful pattern matching system for waiting for expected output from child processes. The expect system is the core of pexpect's automation capabilities, allowing scripts to wait for specific patterns before proceeding.
The primary methods for pattern matching and synchronization with child processes.
def expect(self, pattern, timeout=-1, searchwindowsize=-1, async_=False, **kw):
"""
Wait for pattern in child output.
Parameters:
- pattern (str, bytes, regex, list): Pattern(s) to match
- timeout (int): Timeout in seconds (-1 for default)
- searchwindowsize (int): Buffer size for pattern search
- async_ (bool): Return asyncio Future on Python 3.4+ (default: False)
- **kw: Additional keyword arguments
Returns:
int or asyncio.Future: Index of matched pattern (0 for single pattern)
Raises:
- TIMEOUT: If pattern not found within timeout
- EOF: If child process terminates before pattern found
"""
def expect_list(self, pattern_list, timeout=-1, searchwindowsize=-1, async_=False, **kw):
"""
Wait for any pattern from a list of patterns.
Parameters:
- pattern_list (list): List of patterns to match
- timeout (int): Timeout in seconds
- searchwindowsize (int): Buffer size for pattern search
- async_ (bool): Return asyncio Future on Python 3.4+ (default: False)
- **kw: Additional keyword arguments
Returns:
int or asyncio.Future: Index of matched pattern in the list
"""
def expect_exact(self, pattern_list, timeout=-1, searchwindowsize=-1, async_=False, **kw):
"""
Wait for exact string matches (no regex interpretation).
Parameters:
- pattern_list (list): List of exact strings to match
- timeout (int): Timeout in seconds
- searchwindowsize (int): Buffer size for pattern search
- async_ (bool): Return asyncio Future on Python 3.4+ (default: False)
- **kw: Additional keyword arguments
Returns:
int or asyncio.Future: Index of matched pattern in the list
"""
def expect_loop(self, searcher, timeout=-1):
"""
Core expect loop that handles the actual pattern matching.
Parameters:
- searcher (searcher_string or searcher_re): Pattern searcher object
- timeout (int): Timeout in seconds
Returns:
int: Index of matched pattern
"""
def compile_pattern_list(self, patterns):
"""
Compile list of patterns into searcher objects.
Parameters:
- patterns (list): List of patterns (strings, regex, EOF, TIMEOUT)
Returns:
searcher_string or searcher_re: Compiled pattern searcher
"""Classes that handle different types of pattern matching internally.
class searcher_string:
"""
Fast string searcher for exact string matching.
"""
def __init__(self, strings, index):
"""
Parameters:
- strings (list): List of strings to search for
- index (int): Starting index for pattern numbering
"""
eof_index: int # Index returned when EOF encountered
timeout_index: int # Index returned when timeout occurs
class searcher_re:
"""
Regular expression searcher for pattern matching.
"""
def __init__(self, patterns, index):
"""
Parameters:
- patterns (list): List of regex patterns (compiled or string)
- index (int): Starting index for pattern numbering
"""
eof_index: int # Index returned when EOF encountered
timeout_index: int # Index returned when timeout occursInternal class that manages the expect operations.
class Expecter:
"""
Coordinates pattern searching operations.
"""
def __init__(self, spawn, searcher, searchwindowsize=-1):
"""
Parameters:
- spawn: The spawn object being monitored
- searcher: Pattern searcher object
- searchwindowsize (int): Size of search window
"""
def do_search(self, window, freshlen):
"""
Perform pattern search on data window.
Parameters:
- window (bytes): Data buffer to search
- freshlen (int): Length of new data in buffer
Returns:
int: Match index or -1 if no match
"""
def existing_data(self):
"""Handle search on existing buffered data."""
def new_data(self, data):
"""Handle search on newly received data."""# Simple string matching
child.expect('Password:')
child.expect(b'binary_string')
# Multiple string options
index = child.expect(['choice1', 'choice2', 'choice3'])
if index == 0:
print("Got choice1")
elif index == 1:
print("Got choice2")import re
# Regex patterns
child.expect(r'\$ ') # Shell prompt
child.expect(r'[Pp]assword:') # Case insensitive password prompt
child.expect(re.compile(r'\d+\.\d+\.\d+\.\d+')) # IP address
# Compiled regex patterns
pattern = re.compile(r'([A-Za-z]+): (\d+)')
child.expect(pattern)
# Access captured groups via child.match.groups()# Built-in special patterns
child.expect(pexpect.EOF) # Wait for process to end
child.expect(pexpect.TIMEOUT) # Handle timeout explicitly
# Mixed pattern lists
patterns = [
'success', # String pattern
re.compile(r'error: (.+)'), # Regex pattern
pexpect.TIMEOUT, # Timeout handler
pexpect.EOF # EOF handler
]
index = child.expect(patterns, timeout=30)# Limit search buffer size for performance
child.expect('pattern', searchwindowsize=1000)
# Useful for streaming data or very long output
child = pexpect.spawn('tail -f /var/log/messages')
child.expect('ERROR', searchwindowsize=500)import pexpect
child = pexpect.spawn('slow_command')
try:
index = child.expect(['Success', 'Error'], timeout=10)
if index == 0:
print("Command succeeded")
else:
print("Command failed")
except pexpect.TIMEOUT:
print("Command timed out")
# Optionally kill the process
child.kill(signal.SIGTERM)
except pexpect.EOF:
print("Process ended unexpectedly")import pexpect
import re
child = pexpect.spawn('some_command')
# String matching - access matched text
child.expect('Found: ')
print(f"Before match: {child.before}")
print(f"Matched text: {child.after}")
# Regex matching - access capture groups
pattern = re.compile(r'Result: (\d+) items processed')
child.expect(pattern)
print(f"Items processed: {child.match.group(1)}")
# Multiple patterns - check which matched
patterns = ['success', 'warning', 'error']
index = child.expect(patterns)
print(f"Matched pattern #{index}: {patterns[index]}")import pexpect
# Simple login automation
child = pexpect.spawn('ssh user@server')
child.expect('Password:')
child.sendline('mypassword')
child.expect('$ ')
print("Successfully logged in")import pexpect
child = pexpect.spawn('ssh user@server')
# Handle multiple possible responses
index = child.expect([
'Password:', # Index 0: Password prompt
'Are you sure', # Index 1: Host key verification
'Permission denied', # Index 2: Already failed
pexpect.TIMEOUT # Index 3: Timeout
])
if index == 0:
child.sendline('mypassword')
child.expect('$ ')
elif index == 1:
child.sendline('yes')
child.expect('Password:')
child.sendline('mypassword')
child.expect('$ ')
elif index == 2:
print("Login failed - permission denied")
child.close()
elif index == 3:
print("Connection timed out")
child.close()import pexpect
import re
child = pexpect.spawn('ping google.com')
# Match ping statistics with regex
pattern = re.compile(r'(\d+) packets transmitted, (\d+) received')
child.expect(pattern, timeout=60)
transmitted = child.match.group(1)
received = child.match.group(2)
print(f"Transmitted: {transmitted}, Received: {received}")import pexpect
# Monitor log file for errors
child = pexpect.spawn('tail -f /var/log/application.log')
while True:
try:
index = child.expect([
re.compile(r'ERROR: (.+)'),
re.compile(r'WARNING: (.+)'),
pexpect.TIMEOUT
], timeout=5)
if index == 0: # Error found
error_msg = child.match.group(1)
print(f"Error detected: {error_msg}")
elif index == 1: # Warning found
warning_msg = child.match.group(1)
print(f"Warning: {warning_msg}")
# timeout index (2) - continue monitoring
except KeyboardInterrupt:
break
child.close()import pexpect
child = pexpect.spawn('interactive_program')
# Use expect_exact for literal string matching (no regex interpretation)
# Useful when patterns contain regex special characters
child.expect_exact(['[INFO]', '[ERROR]', '[DEBUG]'])
# This avoids issues with square brackets being interpreted as regex character classesInstall with Tessl CLI
npx tessl i tessl/pypi-pexpect