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

Python2升级到Python3后Popen调用C++程序无法接收输入如何解决

问题根因
  • Python3的subprocess.Popen返回的标准输入/输出/错误流默认是字节流,和Python2默认的字符串流逻辑完全不同
  • 原代码写入输入后没有手动刷新缓冲区也没有关闭标准输入,C++程序始终没收到完整输入,一直阻塞在读取输入的步骤,后续stdout.readlines()也会跟着永久阻塞
  • 编译阶段的错误判断逻辑在Python3中完全失效:communicate()返回的stderr是字节类型,直接判断字符串'error'是否存在永远返回False,会直接跳过所有测试用例评分逻辑
可直接落地的修改方案

所有测试用例统一按以下逻辑修改,不需要手动write、不需要强制杀进程,communicate会自动处理输入发送、流关闭、进程等待的所有逻辑:

  1. 提前拼接好当前测试用例的所有输入内容,编码为utf-8字节
  2. 调用communicate(输入字节)方法拿到进程返回的stdout、stderr
  3. 将stdout解码为字符串后按行拆分,再做结果判断
  4. 编译阶段的错误判断先把stderr解码为字符串再做匹配
修改后的核心代码示例
from subprocess import Popen, PIPE

def tester_1(filename):
    # 检测恶意system调用逻辑保留
    if 'system' in open(filename, encoding='utf-8').read():
        return 2
    # 编译阶段修改:错误输出先解码再判断
    p = Popen(["g++", filename], stdout=PIPE, stderr=PIPE)
    _, compile_err = p.communicate()
    grade = 4
    # 字节直接判断是否有编译错误即可
    if b'error' not in compile_err:
        grade += 1
        # 第一个测试用例修改示例
        test1_input = f"{3}\n{5}\n{7}\n{18}\n".encode('utf-8')
        p = Popen(['./a.out'], stdout=PIPE, stdin=PIPE, stderr=PIPE)
        stdout, _ = p.communicate(test1_input)
        result = stdout.decode('utf-8').splitlines()
        if len(result) >= 2:
            if "6" in result[-1] and "odd" in result[-1]:
                grade += 1
            if "18" in result[-2] and "even" in result[-2]:
                grade += 1

        # 第二个测试用例
        try:
            test2_input = f"{2}\n{6}\n{7}\n".encode('utf-8')
            p = Popen(['./a.out'], stdout=PIPE, stdin=PIPE, stderr=PIPE)
            stdout, _ = p.communicate(test2_input)
            result = stdout.decode('utf-8').splitlines()
            if len(result) >= 2:
                if "7" in result[-1] and "odd" in result[-1]:
                    grade += 1
                if "6" in result[-2] and "even" in result[-2]:
                    grade += 1
        except:
            pass

        # 第三个测试用例
        try:
            test3_input = f"{6}\n{2}\n{2}\n{4}\n{3}\n{5}\n{3}\n".encode('utf-8')
            p = Popen(['./a.out'], stdout=PIPE, stdin=PIPE, stderr=PIPE)
            stdout, _ = p.communicate(test3_input)
            result = stdout.decode('utf-8').splitlines()
            if len(result) >= 2:
                if "2.66" in result[-2] and "even" in result[-2]:
                    grade += 1
                if "3.66" in result[-1] and "odd" in result[-1]:
                    grade += 1
        except:
            pass

        grade = min(grade, 10)
    return grade
额外优化建议
  • 可以去掉shell=True参数,直接调用二进制文件不会有安全问题,还能减少进程开销
  • 加超时参数避免学生代码死循环卡住评测脚本:p.communicate(test_input, timeout=5),超时会抛出异常可以直接判对应测试用例0分

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 16:36:03