You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

使用方法

  1. 安装expect(如Debian系:sudo apt install expect)
  2. 赋予脚本执行权限:chmod +x repl_shell.sh
  3. 执行:./repl_shell.sh script.py

内容的提问来源于stack exchange,提问作者Thomas Weise

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 16:45:55