CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pexpect

Pure Python module for spawning child applications and controlling them automatically with expect-like functionality.

Pending
Overview
Eval results
Files

pattern-matching.mddocs/

Pattern Matching and Expect Operations

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.

Capabilities

Core Expect Methods

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
    """

Pattern Searcher Classes

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 occurs

Pattern Matching Coordinator

Internal 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."""

Pattern Types and Syntax

String Patterns

# 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")

Regular Expression Patterns

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()

Special Patterns

# 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)

Advanced Pattern Matching

Using Search Window Size

# 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)

Timeout Handling

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")

Accessing Match Results

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]}")

Usage Examples

Basic Pattern Matching

import pexpect

# Simple login automation
child = pexpect.spawn('ssh user@server')
child.expect('Password:')
child.sendline('mypassword')
child.expect('$ ')
print("Successfully logged in")

Handling Multiple Scenarios

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()

Complex Regex Matching

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}")

Continuous Monitoring

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()

Exact String Matching

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 classes

Install with Tessl CLI

npx tessl i tessl/pypi-pexpect

docs

alternative-spawning.md

index.md

pattern-matching.md

process-control.md

repl-automation.md

ssh-operations.md

utilities.md

tile.json