专栏文章

使用 python 的 subprocess 模块实现多平台的 stdio 交互题对拍

科技·工程参与者 5已保存评论 9

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
9 条
当前快照
1 份
快照标识符
@mkr4oxtj
此快照首次捕获于
2026/01/24 01:02
4 周前
此快照最后确认于
2026/02/19 01:15
13 小时前
查看原文
曾苦于 stdio 交互题的对拍,发现网上没有多少相关的文章。我自己处理的方法是把 stdio 交互题改造为函数式交互题。虽然解决了问题,但是还是比较繁琐。
在此之后,我看到了一篇文章 交互题本机评测器 - Sshwy's Notes,这是在 linux 下的实现,虽然可以解决问题,但是还是不能在 Windows 下方便地使用。
但是它使用管道通信的方法给了我很大的启发,而 python 的 subprocess 模块提供了一种多平台管道通信的实现方法。
下面是我用 python 的 subprocess 模块实现的 stdio 交互题对拍器:
PYTHON
import sys
import subprocess
from threading import Thread, Lock

stop = False

def judger(argv):
    if len(argv) != 3:
        print(f"Usage: {argv[0]} [command1] [command2]", file=sys.stderr)
        return 1
    
    command1 = argv[1]
    command2 = argv[2]

    def run_command(name, p1, p2):
        global stop
        while True:
            lock = Lock()
            lock.acquire()
            line = p1.stdout.readline()
            if not line or stop:
                stop = True
                lock.release()
                break
            print(name + ": " + line.decode(), end="")
            p2.stdin.write(line)
            p2.stdin.flush()
            lock.release()

    p1 = subprocess.Popen(command1, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)
    p2 = subprocess.Popen(command2, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)

    t1 = Thread(target=run_command, args=(command1, p1, p2))
    t2 = Thread(target=run_command, args=(command2, p2, p1))

    t1.start()
    t2.start()

    p1.wait()
    p2.wait()

    return 0

if __name__ == "__main__":
    sys.exit(judger(sys.argv))
使用方法:
BASH
$ cd demo
$ g++ ./problem.cpp -o ./problem
$ g++ ./grader.cpp -o ./grader
$ python ../interactive.py ./problem ./grader
./grader: 514
./problem: ? 258
./grader: 0     
./problem: ? 129
./grader: 0     
./problem: ? 65 
./grader: 1
./problem: ? 97
./grader: 1
./problem: ? 113
./grader: 1
./problem: ? 121
./grader: 0
./problem: ? 117
./grader: 0
./problem: ? 115
./grader: 0
./problem: ? 114
./grader: 1
./problem: ! 114
AC
$ 
使用了 testlib 的交互库也是可以的:
CPP
$ cd testlib_demo
$ g++ ./problem.cpp -o ./problem
$ g++ ./grader.cpp -o ./grader
$ python ../interactive.py ./problem "./grader in.txt out.txt"
./grader in.txt out.txt: 39 600
./problem: 639
ok !
$ 
在 Github 上的链接:Github

评论

9 条评论,欢迎与作者交流。

正在加载评论...