3

我正在为我的学生(我是导师)开发代码检查器。print该项目是他们编写了一个使用关键字打印特定字符串的函数。我希望能够通过存储并匹配到列表(或类似的东西)来测试他们打印的内容。基本设置是:

def checker():
    #run user code
    do some other things like save and check error messages etc

现在在这个checker函数的某个地方,我希望能够跟踪打印的内容。在 Javascript 中,我能够执行以下操作:

var logs = [];
var hold_logger = console.log //saves the console.log so nothing gets ruined
console.log = function (x) { logs.push(x) };

现在,当我运行学生代码时,它不会打印到控制台,而是将值推送到logs. 我想在 Python 2.7 中实现同样的目标。

4

3 回答 3

7

您可以将不同的类似文件的对象分配给sys.stdout; 打印的任何内容都会写入该对象。

您可以使用io.BytesIO()对象来替换stdout

import sys
from io import BytesIO

orig_stdout, sys.stdout = BytesIO()

io是来自 Python 3 的更新、更强大的 I/O 库,在 Python 2 中也可用;io.BytesIO()是更健壮的版本StringIO.StringIO()

然后,您可以通过调用检查打印的内容sys.stdout.getvalue();完成后,您可以从orig_stdout.

演示:

>>> import sys
>>> from io import BytesIO
>>> orig_stdout, sys.stdout = sys.stdout, BytesIO()
>>> print 'Hello world!'
>>> output = sys.stdout.getvalue()
>>> sys.stdout = orig_stdout
>>> output
'Hello world!\n'

请注意,我sys.stdout是从较早的参考资料中恢复的。您也可以使用sys.__stdout__只要没有其他东西可以替代sys.stdout;保存对现在sys.stdout指向的内容的引用更安全。

于 2013-08-08T21:26:34.550 回答
1

这是一种方法 - 您可以将标准输出文件对象替换为自定义对象:

import sys

# A very basic logging class (it should really implement all the file object methods, but for your purposes, this will probably suffice.
class basicLogger:
    def __init__(self):
        self.log = []
    def write(self, msg):
        self.log.append(msg)
    def writelines(self, msgs):
        for msg in msgs:
            self.log.append(msg)

log = basicLogger()

# Replaces the default output file object with your logger
sys.stdout = log

def checker():
    #run user code
    print "hello!"
    print
    print "I am a student!"

checker()

# This replaces the original output file object.
sys.stdout = sys.__stdout__

print "Print log:"
for msg in log.log:
    print "\t", msg,

输出:

Print log:
    hello!  

    I am a student! 
于 2013-08-08T21:37:24.280 回答
0

您在 Java 中所做的 Python 等价物是sys.stdout用自定义的类似文件的对象替换。

当然,这不仅会抓住他们print;它还会捕获它们的内容sys.stdout.write,或者,根据它们的设置,可能是它们logging.log或它们运行的​​子进程的输出等。但实际上没有办法解决这个问题,因为print它不是你可以替换的函数。(当然,如果您改为教他们 3.x,那就另当别论了。)


但是,根本不这样做可能更简单。只需从 Python 外部捕获标准输出。例如:

for student in student??.py:
    python ${student} > ${student}.out

subprocess或者,如果您坚持,请在 Python中使用 from 执行相同的操作:

output = {student: subprocess.check_output('{}.py'.format(student)) 
          for student in students}

(您可能希望将其包装在捕获和隐藏异常的东西中,但这应该足以让您有这个想法。)

于 2013-08-08T21:26:40.423 回答