模拟input输入并获得print输出的内容

需求源自要进行一次Python考试的判题。题目的答案使用print输出的,我希望获得输出的内容然后与标准答案进行比对,进而做出是否得分的判定。

我的思路是利用io操作,修改用户提交的py源文件,加入一些我的自定义内容,形成一个新的py源文件。

例如,这是用户提交的原始文件

word = input()
word = list(word)
l = len(word)
for i in range(l):
    if(ord(word[i])+3<123):
        word[i]= chr(ord(word[i])+3)
    else:
        word[i]= chr(ord(word[i])+3-122+96)
print(''.join(word))

题目本身并不难,就是凯撒密码,但是作为判卷程序需要模拟input输入和获得学生程序print输出的结果。所以我首先写了一个辅助判卷程序mytest.py

answer = "defghijklmnopqrstuvwxyzabc"
question = "abcdefghijklmnopqrstuvwxyz"


def myinput(a=None):
    return question

然后再写一个程序用来将mytest.py与学生提交的原始程序有机结合一下。结合的目的无非两个:1、模拟input的输入 2、重定向print的输入

生成新程序的程序gen.py(这是生成程序的第一部分)

import os.path
import os
import sys
import mytest


fout_ac = open("result_ac.txt", "a", encoding="utf8")
fout_un = open("result_un.txt", "a", encoding="utf8")

lines = [
    "import mytest\n", "import sys\n", "\n", "input = mytest.myinput\n",
    'sys.stdout = open("result.txt", "w+", encoding="utf8")\n'
]
pyfiles = os.listdir("clean")
pyfile = pyfiles[0]

try:
    #写mytest相关的内容
    with open(pyfile, "w", encoding="utf8") as fw:
        fw.writelines(lines)
    #写学生的源代码
    with open(pyfile, "a", encoding="utf8") as fw:

        f = open(os.path.join("clean", pyfile), "r", encoding="utf8")
        line = f.readline()
        while (line):
            if not line.startswith("import") and not line.startswith("from"):
                fw.write(line + "\n")
            line = f.readline()

        fw.write("\n")
        fw.write("\n")
        fw.write("\n")

        f.close()

新生成的结合了mytest和学生提交的原始程序的py文件

import mytest
import sys

input = mytest.myinput
sys.stdout = open("result.txt", "w+", encoding="utf8")
word = input()

word = list(word)

l = len(word)

for i in range(l):

    if(ord(word[i])+3<123):

        word[i]= chr(ord(word[i])+3)

    else:

        word[i]= chr(ord(word[i])+3-122+96)

print(''.join(word))

这个生成的程序中,将input函数屏蔽为mytest下的myinput函数,这样input函数的返回值就是26个小写字母,然后原封不动的利用学生书写的业务逻辑来处理这26个小写字母。一旦这个新生成的程序运行结束,最后的处理结果被print输出到重定向的result.txt中。

所以,我们继续完成gen的第二部分,运行生成的程序,并读取生成的程序写入到result.txt中的内容,看这个内容是否是我们期望的内容:

import os.path
import os
import sys
import mytest


fout_ac = open("result_ac.txt", "a", encoding="utf8")
fout_un = open("result_un.txt", "a", encoding="utf8")

lines = [
    "import mytest\n", "import sys\n", "\n", "input = mytest.myinput\n",
    'sys.stdout = open("result.txt", "w+", encoding="utf8")\n'
]
pyfiles = os.listdir("clean")
pyfile = pyfiles[0]

try:
    #写mytest相关的内容
    with open(pyfile, "w", encoding="utf8") as fw:
        fw.writelines(lines)
    #写学生的源代码
    with open(pyfile, "a", encoding="utf8") as fw:

        f = open(os.path.join("clean", pyfile), "r", encoding="utf8")
        line = f.readline()
        while (line):
            if not line.startswith("import") and not line.startswith("from"):
                fw.write(line + "\n")
            line = f.readline()

        fw.write("\n")
        fw.write("\n")
        fw.write("\n")

        f.close()
    #运行上面生成的新程序
    os.system("python " + pyfile)
    #如果新生成程序正常执行完毕,此时result.txt中应该有一行输出
    #读取result.txt中的内容
    read_fr_result = open("result.txt", "r+", encoding="utf8")
    #result.txt刚写完数据且处于打开的状态,此时游标位于写入内容的最后
    #所以直接read是读不到任何内容的,需要用seek将游标拨到文件的开头处
    #再进行读入才能读到内容
    read_fr_result.seek(0, 0)
    line = read_fr_result.readline().strip()

    if line == mytest.answer:
        #读取的内容与预置答案一致,将包含学生信息的文件名称写入result_ac.txt文件
        fout_ac.write(pyfile + "\n")
    else:
        raise ValueError()

except:
    #程序的RE WA都会被这个except捕捉
    #无论是RE WA都视为错误,将包含学生信息的文件名称写入result_un.txt文件
    fout_un.write(pyfile + "\n")

在gen.py中,生成了程序后,就调用os.system来运行这个生成的程序。运行的结果无非是两种情况1,程序正确执行,将处理结果写入了result.txt中 2,程序运行错误,这种错误显然都是RE错误,会被except捕获视为不通过。那么程序运行正确,写入result.txt的结果是否正确呢,就需要读出判定。读出前需要seek,原因在代码注释中已经说明。取出的答案符合预期的就AC,否则就是WA扔出异常供except捕获。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值