如何结合标准输入和标准输出?



我是一名从事自动化学生作业检查的教师,我希望当我使用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)

最新更新