我是一名从事自动化学生作业检查的教师,我希望当我使用subprocess.run
运行学生程序时生成的输出文件看起来就像我手动运行时一样。
以下程序
import subprocess
import sys
userInput = open("userInput.txt")
with open("output.txt", "w") as fout:
with open("error.txt", "w") as ferr:
result = subprocess.run(["python","hello.py"], stdin=userInput,stdout=fout,stderr=ferr)
with thishello.py
name = input("Your name: ")
age = input("Your age: ")
print('Hello,',name,"you are",age,"years old")
和thisuserInput.txt
Bob
27
生成以下output.txt
Your name: Your age: Hello, Bob you are 27 years old
如何让程序生成output.txt该文件看起来与我简单地运行hello.py时相同(其中标准输入也显示在标准输出中)。
Your name: Bob
Your age: 27
Hello, Bob you are 27 years old
我在Windows 10系统上做这个。
这是一项比乍看起来复杂得多的任务。您基本上是在试图监视从标准输入读取和写入标准输出的数据。
简单的解决方案是使用pexpect库。https://pexpect.readthedocs.io/en/stable/index.html 例如:
import pexpect
child = pexpect.spawn('./hello.py', logfile=open('output.txt', 'wb'))
child.expect('name:')
child.send('Bobn')
child.expect('age:')
child.send('27n')
child.expect('H') # Necessary to get the last line of output.
输出与stdin信息重复。我不知道为什么它会这样做。
Your name: Bob
Bob
Your age: 27
27
Hello, Bob you are 27 years old
如果您想自己重新实现pexpect,则需要使用subprocess.Popen()
并直接写入p.stdin
并从p.stdout
读取。这需要将p.stdout
更改为非阻塞。
import os
import fcntl
import subprocess
p = subprocess.Popen(['hello.py'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
flags = fcntl.fcntl(p.stdout, fcntl.F_GETFL)
fcntl.fcntl(p.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK)
while True:
try:
out = os.read(p.stdout.fileno(), 100000).decode("utf-8").strip()
# process output
except BlockingIOError:
time.sleep(0.1)