如何在Ubuntu的Python 3.12 REPL中执行脚本并获手动输入式输出?
实现Python脚本模拟交互式REPL执行输出
需求说明
将普通Python脚本(或带REPL提示符的脚本)执行后,输出与手动在Python交互式环境(REPL)输入完全一致的内容,包括版本信息、>>>/...提示符、表达式返回值、print输出等。
方案一:处理无提示符的原始脚本
使用Python内置的code模块模拟REPL环境,逐行执行脚本并生成对应输出。
实现脚本(repl_simulator.py)
import code import sys from io import StringIO def simulate_repl(script_path): # 读取目标脚本内容 with open(script_path, 'r') as f: script_lines = [line.rstrip('\n') for line in f if line.strip()] # 重定向标准输出以捕获内容 old_stdout = sys.stdout output_buffer = StringIO() sys.stdout = output_buffer try: # 打印REPL启动时的版本信息 print(code.interact.banner) # 初始化交互式控制台上下文 console_locals = {} console = code.InteractiveConsole(locals=console_locals) for line in script_lines: # 根据缩进打印对应提示符 if line.startswith((' ', '\t')): print(f'... {line}') else: print(f'>>> {line}') # 区分表达式与语句:表达式执行后打印返回值,语句直接执行 try: # 尝试作为表达式执行 result = eval(line, console_locals) if result is not None: print(result) except SyntaxError: # 是语句,通过控制台执行 console.push(line) finally: # 恢复标准输出 sys.stdout = old_stdout # 输出最终结果 print(output_buffer.getvalue(), end='') if __name__ == '__main__': if len(sys.argv) != 2: print(f"用法: {sys.argv[0]} <脚本路径>") sys.exit(1) simulate_repl(sys.argv[1])
使用方法
将目标脚本(如示例中的script.py)传入执行:
python3 repl_simulator.py script.py
方案二:处理带REPL提示符的脚本
如果脚本已经包含>>>和...提示符,可以利用doctest模块直接解析执行,过滤掉测试相关的额外输出。
实现脚本(run_prompted.py)
import doctest import sys import code from io import StringIO def run_prompted_script(script_path): with open(script_path, 'r') as f: script_content = f.read() old_stdout = sys.stdout output_buffer = StringIO() sys.stdout = output_buffer try: # 打印REPL版本信息 print(code.interact.banner) # 执行带提示符的脚本内容 doctest.run_docstring_examples(script_content, globals(), name='__main__', verbose=True) finally: sys.stdout = old_stdout # 过滤doctest的测试结果行,保留纯REPL输出 filtered_output = [] for line in output_buffer.getvalue().splitlines(): if not line.startswith(('1 items', '0 failures', 'TestResults')): filtered_output.append(line) print('\n'.join(filtered_output)) if __name__ == '__main__': if len(sys.argv) != 2: print(f"用法: {sys.argv[0]} <带提示符的脚本路径>") sys.exit(1) run_prompted_script(sys.argv[1])
使用方法
将带提示符的脚本(如示例中的带>>>的脚本)传入执行:
python3 run_prompted.py prompted_script.py
方案三:Bash+Expect方案(需额外依赖)
如果偏好使用Shell脚本,可以借助expect工具模拟手动输入到Python REPL的过程:
实现脚本(repl_shell.sh)
#!/bin/bash if [ $# -ne 1 ]; then echo "用法: $0 <脚本路径>" exit 1 fi SCRIPT_PATH="$1" # 用expect模拟交互式输入 expect << EOF set fp [open "$SCRIPT_PATH" r] spawn python3 expect ">>> " while {[gets \$fp line] != -1} { if {[string trim \$line] eq ""} { continue } send -- "\$line\r" # 根据行缩进判断等待的提示符 if {[string match {[ \t]*} \$line]} { expect "... " } else { expect ">>> " } } send -- "exit()\r" expect eof close \$fp EOF
使用方法
- 安装
expect(如Debian系:sudo apt install expect) - 赋予脚本执行权限:
chmod +x repl_shell.sh - 执行:
./repl_shell.sh script.py
内容的提问来源于stack exchange,提问作者Thomas Weise
相关产品推荐
相关产品推荐

