{"id":237,"library":"pexpect","title":"Pexpect","description":"Pure Python module for spawning child applications and controlling them — automates interactive CLI programs like ssh, ftp, passwd. Current version is 4.9.0 (Nov 2023). pexpect.spawn requires Unix/Linux (uses the pty module) — not available on Windows. For Windows use pexpect.PopenSpawn instead. Low maintenance activity since 2023.","status":"active","version":"4.9.0","language":"python","source_language":"en","source_url":"https://pexpect.readthedocs.io/en/stable/","tags":["cli-automation","interactive","ssh","terminal","subprocess","expect","testing"],"install":[{"cmd":"pip install pexpect","lang":"bash","label":"Standard"}],"dependencies":[{"reason":"Required on Unix for pty-based spawn. Installed automatically.","package":"ptyprocess>=0.5","optional":false}],"imports":[{"note":"pexpect.spawn only works on Unix/Linux. On Windows use pexpect.PopenSpawn. Pass encoding='utf-8' to get str instead of bytes from before/after. TIMEOUT and EOF are passed to expect() as patterns, not caught as exceptions.","wrong":"# On Windows, pexpect.spawn raises ImportError — pty not available:\nimport pexpect\nchild = pexpect.spawn('cmd.exe')  # ImportError on Windows\n\n# TIMEOUT and EOF are not exceptions to catch with except:\ntry:\n    child.expect('pattern')\nexcept pexpect.TIMEOUT:  # TypeError — TIMEOUT is a class, use as pattern\n    pass","symbol":"pexpect.spawn","correct":"import pexpect\n\n# Unix/Linux only — uses pty module\nchild = pexpect.spawn('ssh user@host', encoding='utf-8', timeout=30)\n\n# expect() returns index of matched pattern (or raises TIMEOUT/EOF)\nindex = child.expect(['password:', 'yes/no', pexpect.EOF, pexpect.TIMEOUT])\n\nif index == 0:\n    child.sendline('mysecretpassword')\nelif index == 1:\n    child.sendline('yes')\nelif index == 2:\n    print('Connection closed (EOF)')\nelif index == 3:\n    raise TimeoutError('SSH timed out')\n\n# Wait for shell prompt\nchild.expect(r'\\$')\nchild.sendline('ls -la')\nchild.expect(r'\\$')\nprint(child.before)"}],"quickstart":{"code":"import pexpect\n\n# Basic spawn with string encoding (recommended)\nchild = pexpect.spawn(\n    'python3 -c \"name = input(\\\"Name: \\\"); print(f\\\"Hello {name}!\\\")\"',\n    encoding='utf-8',\n    timeout=10\n)\n\n# expect() waits for a pattern, returns the index of the match\nchild.expect('Name: ')\nchild.sendline('Alice')\nchild.expect(pexpect.EOF)   # wait for program to finish\nprint(child.before)          # 'Hello Alice!\\r\\n'\n\n# Multi-pattern expect\nindex = child.expect(['pattern1', 'pattern2', pexpect.EOF, pexpect.TIMEOUT])\n# index 0 = matched 'pattern1'\n# index 1 = matched 'pattern2'\n# index 2 = EOF (process ended)\n# index 3 = timeout\n\n# Windows: use PopenSpawn (no pty, no interactive echo)\nfrom pexpect import popen_spawn\nchild = popen_spawn.PopenSpawn('python --version', encoding='utf-8')\nchild.expect(pexpect.EOF)\nprint(child.before)","lang":"python","description":"Always pass encoding='utf-8'. expect() returns index. Use PopenSpawn on Windows."},"warnings":[{"fix":"On Windows use pexpect.popen_spawn.PopenSpawn instead. PopenSpawn lacks interactive TTY features but works cross-platform.","message":"pexpect.spawn is not available on Windows — it requires the pty module which only exists on Unix. Importing pexpect works, but calling pexpect.spawn() raises ImportError or OSError on Windows.","severity":"breaking","affected_versions":"all"},{"fix":"Replace child.expect('pattern', async=True) with child.expect('pattern', async_=True)","message":"The async= parameter was renamed to async_= as async became a Python keyword in 3.7. Using async= raises SyntaxError on Python 3.7+.","severity":"breaking","affected_versions":">= 4.3"},{"fix":"Always pass encoding='utf-8': pexpect.spawn('cmd', encoding='utf-8'). Then expect() patterns and before/after are strings.","message":"Without encoding='utf-8', child.before and child.after return bytes, not str. Most tutorials show str patterns but they fail with bytes. Always specify encoding at spawn time.","severity":"gotcha","affected_versions":"all"},{"fix":"Pass them as patterns in the expect list and check the returned index: index = child.expect(['pattern', pexpect.EOF, pexpect.TIMEOUT]); if index == 2: handle_timeout()","message":"pexpect.TIMEOUT and pexpect.EOF are classes, not exceptions. They are passed to expect() as patterns (expect([pexpect.EOF, pexpect.TIMEOUT])), not caught with except. Catching them with except does not work as expected.","severity":"gotcha","affected_versions":"all"},{"fix":"To get all output: child.expect(pexpect.EOF); print(child.before) captures everything before EOF.","message":"child.before contains output BEFORE the matched pattern. child.after contains the matched pattern itself. Output AFTER the match is buffered internally. Accessing child.before after EOF gives all remaining output.","severity":"gotcha","affected_versions":"all"},{"fix":"Use the pyte package for terminal emulation instead.","message":"pexpect.screen and pexpect.ANSI modules are deprecated. Do not import from them.","severity":"gotcha","affected_versions":"all"},{"fix":"Inspect the contents of `child.before` for error messages or diagnostic output from the child process. Fix the underlying issue in the child's command or script. To handle expected terminations gracefully without raising an exception, add `pexpect.EOF` to your expect list (e.g., `child.expect(['your pattern', pexpect.EOF])`) and check the returned index.","message":"The child process terminated prematurely, likely due to an internal error (e.g., SyntaxError, unhandled exception, command not found, permissions error) or reaching its natural end of output, before the expected pattern could be found. Pexpect reports this as `pexpect.exceptions.EOF`.","severity":"gotcha","affected_versions":"all"},{"fix":"Examine the `child.before` buffer for error messages or tracebacks from the child process that explain its termination. Ensure the command or script executed by the child process is syntactically correct and robust, handling its own internal errors gracefully to prevent premature exit.","message":"pexpect.exceptions.EOF can be raised if the child process terminates unexpectedly before the expected pattern is found. This often indicates an error or crash within the child process itself (e.g., SyntaxError, unhandled exception, program exit).","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-05-12T12:10:51.864Z","next_check":"2026-09-27T00:00:00.000Z","problems":[{"fix":"Install pexpect using pip: `pip install pexpect`. If using virtual environments, ensure the environment is activated before installation. If multiple Python versions are present, ensure pexpect is installed for the correct version (e.g., `python3 -m pip install pexpect`).","cause":"The pexpect module is not installed in the Python environment being used, or there's a mismatch between where pexpect was installed and the Python interpreter running the script.","error":"ModuleNotFoundError: No module named 'pexpect'"},{"fix":"On Windows, use `pexpect.popen_spawn.PopenSpawn` instead of `pexpect.spawn`. For other `AttributeError` instances, ensure pexpect is up to date (`pip install --upgrade pexpect`) and that constants like `TIMEOUT` are accessed directly (e.g., `pexpect.TIMEOUT`) if imported as `import pexpect`.","cause":"The `pexpect.spawn` method is not available on Windows because it relies on Unix pseudoterminals (ptys). Additionally, an outdated version of pexpect or an incorrect import statement can lead to similar `AttributeError` messages related to other attributes.","error":"AttributeError: module 'pexpect' has no attribute 'spawn'"},{"fix":"Increase the timeout value when calling `expect()` or `spawn()` (e.g., `child.expect('prompt', timeout=60)` or `pexpect.spawn('command', timeout=None)` for no timeout). Alternatively, include `pexpect.TIMEOUT` in the list of patterns to catch the timeout as a match index rather than an exception.","cause":"The `expect()` method in pexpect raised a `TIMEOUT` exception because the expected pattern was not found within the specified timeout period. The default timeout is 30 seconds.","error":"pexpect.TIMEOUT: Timeout exceeded."},{"fix":"Include `pexpect.EOF` in the list of patterns passed to `expect()` to handle the child exiting gracefully, allowing you to process any output received before the EOF. Review the child process's behavior or the commands sent to ensure it's not exiting prematurely.","cause":"The child process spawned by pexpect has unexpectedly exited or closed its connection, leading to an End Of File (EOF) condition before the expected pattern was matched.","error":"pexpect.EOF: End Of File (EOF) in read()"},{"fix":"Provide the full, absolute path to the executable file (e.g., `pexpect.popen_spawn.PopenSpawn('C:\\Windows\\System32\\OpenSSH\\ssh.exe ...')`) or ensure the executable's directory is correctly added to the system's PATH environment variable.","cause":"This error typically occurs on Windows when using `pexpect.popen_spawn.PopenSpawn` and the command specified as an argument cannot be found in the system's PATH. This is common for commands like 'ssh' which may not be natively in the Windows PATH without specific installations.","error":"FileNotFoundError: [WinError 2] The system can't find the given file."}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":0,"quickstart_tag":"stale","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1,"disk_size":"18.3M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":1,"disk_size":"19M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":1.1,"disk_size":"20.2M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":1.1,"disk_size":"21M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":0.9,"disk_size":"12.1M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":0.9,"disk_size":"13M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":1.2,"disk_size":"11.7M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":1,"disk_size":"12M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1.1,"disk_size":"17.8M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1.1,"disk_size":"18M"}]},"quickstart_checks":{"last_tested":"2026-04-23","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}