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

OI
文章目录

最近苦于 stdio 交互题的对拍,发现网上没有多少相关的文章。我自己处理的方法是把 stdio 交互题改造为函数式交互题。虽然解决了问题,但是还是比较繁琐。

在此之后,我看到了一篇文章 交互题本机评测器 - Sshwy's Notes,这是在 linux 下的实现,虽然可以解决问题,但是还是不能在 Windows 下方便地使用。

但是它使用管道通信的方法给了我很大的启发,而 python 的 subprocess 模块提供了一种多平台管道通信的实现方法。

下面是我用 python 的 subprocess 模块实现的 stdio 交互题对拍器:

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)
    p2 = subprocess.Popen(command2, stdin=subprocess.PIPE, stdout=subprocess.PIPE)

    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))

使用方法:

$ 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
$

在 Github 上的链接:Github

本文作者:ZnPdCo

本文链接: https://znpdco.github.io/blog/2024/07/27/interactive/

本页面的全部内容在 CC BY-SA 4.0SATA 协议之条款下提供,附加条款亦可能应用

评论