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

如何在Python中实时分析执行其他脚本时的终端输入输出?

编程作业实时评分工具解决方案

我要开发一个编程作业评分工具,允许学生自主实现任务,不用限定具体写法。核心需求是实时分析终端的输入与输出,而不是等程序跑完再对比整个stdout。

之前试过subprocess.run、open、subprocess.Popen、exec()和pexpect,现有代码能对比最终输出,但存在漏洞——学生可以用硬编码输出蒙混过关。我不想一次性把整个文本文件作为输入传给程序,而是要逐行输入内容,实时捕获对应输出,验证每个输入的响应是否正确,还能定位复杂作业的特定检查点。


现有问题代码

import os
import subprocess

cwd = os.path.dirname(os.path.abspath(__file__))
expected_input = f"{cwd}/expected_input.txt"
expected_path = f"{cwd}/expected_output.txt"

def get_expected_output(file_path):
    return_str = ""
    with open(file_path, "r") as temp_file:
        for line in temp_file:
            if not line:
                break
            return_str += line
    return return_str

def main():
    expected_output = get_expected_output(expected_path)
    for x in range(1,4):
        test_path = f"{cwd}/test{x}.py"
        with subprocess.Popen(f"python {test_path} < {expected_input}", 
                              stdin=subprocess.PIPE,
                              stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE,
                              shell=True,  
                              text=True
                              ) as proc:
            std_out, std_err = proc.communicate()
            if std_out != expected_output:
                print(f"Expected: \n{expected_output} \n\nActual: \n{std_out}")
                print(f"Take a look at student {x}'s code")
            else:
                print(f"Student {x} finished")

if __name__ == "__main__":
    main()

学生代码示例

正常通过的代码(Ex1)

import sys

def main():
    while(True):
        print("Please enter a number or type exit")
        user_input = input()
        if user_input == 'exit':
            sys.exit()
        try:
            num = float(user_input)
            print(f"{num} x 2 = {num*2}")
        except ValueError:
            print("Invalid input")

if __name__ == "__main__":
    main()

(注:原代码存在逻辑bug,将input()转成float后与字符串'exit'比较永远不成立,此处已修正)

硬编码蒙混的代码(Ex2)

print("Please enter a number or type exit")
print("1.0 x 2 = 2.0")
print("Please enter a number or type exit")
print("2.0 x 2 = 4.0")
print("Please enter a number or type exit")
print("3.0 x 2 = 6.0")
print("Please enter a number or type exit")

解决方案:逐行交互验证

用pexpect可以实现逐行输入并实时捕获输出,精准验证每个输入对应的响应。以下是改进后的代码:

import os
import pexpect

cwd = os.path.dirname(os.path.abspath(__file__))
# 定义测试用例:输入内容与对应预期输出
test_cases = [
    ("1.0", "1.0 x 2 = 2.0"),
    ("2.0", "2.0 x 2 = 4.0"),
    ("3.0", "3.0 x 2 = 6.0"),
    ("exit", pexpect.EOF)  # 输入exit后进程应正常结束
]

def test_student_code(script_path):
    try:
        # 启动学生的Python脚本进程
        child = pexpect.spawn(f"python {script_path}", cwd=cwd, encoding='utf-8')
        passed = True
        
        for input_str, expected_output in test_cases:
            # 等待程序输出提示信息
            child.expect("Please enter a number or type exit")
            # 向进程输入测试内容
            child.sendline(input_str)
            
            # 处理进程结束的情况
            if expected_output == pexpect.EOF:
                try:
                    child.expect(pexpect.EOF, timeout=1)
                except pexpect.TIMEOUT:
                    print("错误:输入'exit'后进程未正常结束")
                    passed = False
                continue
            
            # 验证程序的响应输出是否符合预期
            child.expect(expected_output, timeout=1)
        
        print("测试通过" if passed else "测试未通过")
            
    except pexpect.TIMEOUT:
        print("超时:程序未按预期输出,疑似硬编码或逻辑错误")
    except pexpect.EOF:
        print("意外退出:程序提前结束,未完成所有测试用例")
    finally:
        if 'child' in locals():
            child.close()

def main():
    for x in range(1,4):
        test_path = f"{cwd}/test{x}.py"
        print(f"===== 测试学生{x}的代码 =====")
        test_student_code(test_path)

if __name__ == "__main__":
    main()

方案说明

  • 用pexpect.spawn启动交互式进程,替代一次性输入所有内容的方式,实现真实的终端交互逻辑
  • 针对每个测试用例,先等待程序输出提示信息,再输入测试值,最后验证对应输出,完全模拟用户操作流程
  • 能精准识别硬编码行为:硬编码代码只会按固定顺序输出内容,不会响应输入,第一次输入后就会超时,无法匹配预期输出
  • 可灵活扩展测试用例,比如加入非数字输入等异常场景,验证程序的错误处理能力

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 20:35:54