Python,同时记录日志并将其打印到标准输出

12
我有一个很长的Python脚本,经常使用print语句,我想知道是否可能添加一些代码来将所有的print语句记录在文本文件或类似的东西中。我仍然希望所有的print语句都能显示在命令行中,因为用户在程序中会被提示。如果可能的话,记录用户输入也会很有益。

我找到了这个网站,它在某种程度上回答了我的问题,但是使“print”语句不再打印到命令行。:
重定向Python“print”输出到日志记录器

1
@Robᵩ 哈哈哈 - Stephan
1
@Stephan - 我不觉得我很有趣。我正在努力理解 OP 实际想要我们做什么。 - Robᵩ
@Robᵩ 我想他是在问如何使用一个语句使print“hi”同时输出到两个不同的地方。 - Stephan
5个回答

18

你可以将这个添加到你的脚本中:

import sys
sys.stdout = open('logfile', 'w')

这将使打印语句写入logfile

如果您希望选择将内容打印到stdout和文件,请尝试以下方法:

class Tee(object):
    def __init__(self, *files):
        self.files = files
    def write(self, obj):
        for f in self.files:
            f.write(obj)

f = open('logfile', 'w')
backup = sys.stdout
sys.stdout = Tee(sys.stdout, f)

print "hello world"  # this should appear in stdout and in file

要恢复仅在控制台打印,请恢复“备份”

sys.stdout = backup

10

这里是一个能够实现您所描述功能的程序:

#! /usr/bin/python3

class Tee:
    def write(self, *args, **kwargs):
        self.out1.write(*args, **kwargs)
        self.out2.write(*args, **kwargs)
    def __init__(self, out1, out2):
        self.out1 = out1
        self.out2 = out2

import sys
sys.stdout = Tee(open("/tmp/log.txt", "w"), sys.stdout)

print("hello")

1
你们为什么都使用了一个类,并且它们都被称为 Tee - Stephan
1
我使用了一个类,因为print最终会调用sys.stdout.write()。由于我正在替换sys.stdout,所以我的替代品需要有一个.write()。我将其称为Tee,以纪念unix tee程序,它本身是以同名的管道配件命名的。 - Robᵩ
有趣。你是否也独立运行了我的程序,没有加入任何你的代码?它是否生成了一个非空的 /tmp/log.txt 文件呢? - Robᵩ
@reddman - 你可以尝试在Tee.write()中添加self.out1.flush()self.out2.flush() - Robᵩ

5
尝试在Python 3.7上使用最佳答案时,我遇到了以下异常:
    Exception ignored in: <__main__.Logger object at 0x7f04083760f0>
    AttributeError: 'Logger' object has no attribute 'flush'

我添加了以下函数使其正常工作:
    def flush(self):
        pass

3
如果您使用内置的日志模块,您可以根据需要配置记录器的输出:写入文件、数据库、电子邮件等。然而,您似乎混淆了打印用于两种不同的用途:记录程序流以供以后检查和提示。真正的工作是将“print”的这两种用法拆分为不同的函数,以便在每个位置得到所需内容。
许多人替换Python的通用sys.stdout和sys.stderr以自动执行对发送到控制台的文本进行处理的操作。真正的控制台输出始终驻留在sys.__stdout__sys.__stderr__中(因此您不需要担心如何“丢失”它),但是如果您将具有与文件相同方法的任何对象放入变量sys.stdoutsys.stderr中,则可以对输出过程进行任何操作。

-2

嗯...实现自己的print()函数和装饰器来记录传递给print函数的任何内容,这难吗?

def logger(func):
    def inner(*args, **kwargs):
        log(*args, **kwargs)  # your logging logic
        return func(*args, **kwargs)
    return inner

@logger
def lprint(string_to_print):
    print(string_to_print)   

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接