【问题标题】:Logging isn't working properly日志记录无法正常工作
【发布时间】:2014-10-31 18:54:09
【问题描述】:

所以我正在尝试编写一个装饰器来记录标准输出,同时打印它。重点是分叉输出,以便它显示在控制台中,并被记录下来。这就是我目前所拥有的:

from time import time
import tempfile
import sys
import datetime 

def printUsingTempFile(f):

    def wrapper(*a, **ka):
        with open('sysLog.txt', 'a')  as logFile:
            with tempfile.NamedTemporaryFile() as f:
                sys.stdout = f
                sys.stderr = f 

                retVal = f(*a, **ka)

                f.flush(); f.seek(0); logFile.write('\n'.join(f.readlines()))
                f.flush(); f.seek(0); sys.__stdout__.write('\n'.join(f.readlines()))

                sys.stdout = sys.__stdout__
                sys.stderr = sys.__stderr__

        return retVal
    return wrapper 

if __name__ == '__main__':

    @printUsingTempFile
    def someFunc(abc='Hello!!!'):
        '''
        This is the docstring of the someFunc function.
        '''
        print abc
        return 1

    someFunc('Print something here')

我是这样运行的:

In [18]: !python utility.py

因为如果我使用 run 函数运行,愚蠢的 iPython 窗口会关闭。

我在目录中得到一个名为'sysLog.txt' 的新文件,但它是空的。也没有任何输出可见。没有错误或任何东西。根本不值一提!对此感到有些沮丧。不知道如何调试这段代码:(

编辑:

我意识到我没有寻找两次,所以我更新了代码。我尝试了以下代码:

def printUsingTempFile1():

    with open('sysLog.txt', 'a')  as logFile:
        with tempfile.NamedTemporaryFile() as f:
            sys.stdout = f
            sys.stderr = f 

            print 'This is something ...'

            f.flush(); f.seek(0); logFile.write('\n'.join(f.readlines()))
            f.flush(); f.seek(0); sys.__stdout__.write('\n'.join(f.readlines()))

        sys.stdout = sys.__stdout__
        sys.stderr = sys.__stderr__

而且这个功能似乎工作正常。

【问题讨论】:

  • 不要写入文件并从中读取,而是通过创建您自己的LoggingWriter 来反转该过程,其中write(self, value) 方法将写入原始stdout 和您的记录器。
  • 现在工作。感谢桑杰。
  • 重点是,写入文件并回读非常浪费资源;)
  • @Wolph 我想我明白你在说什么。听起来很有趣。我也试试。谢谢!
  • 您可能还想研究使用 python 日志记录模块,您可以在其中将其配置为记录到控制台、文件等等。

标签: python decorator output-redirect


【解决方案1】:

你为什么使用f作为传入装饰器的函数的名称以及临时文件的名称?我假设对 f(*a, **ka) 的调用出错了,并且由于您已将错误流重定向到临时文件,它会在没有写出任何内容的情况下关闭,因此控制台上什么也没有。

调试此类情况的一个技巧是开始逐个剥离不起作用的代码,并将其降低到最低限度的工作。然后再次努力,直到它开始失败。 :)

编辑

我还建议您在 lint 工具下运行您的代码以捕获此类问题。例如下面贴出的代码:

''' This is a test module '''
import tempfile
import sys


def print_tmp_file(arg):
    ''' Print out the things using temp file '''
    def wrapper(*a, **ka):
    ''' Wrapper function '''
        with open('sysLog.txt', 'a')  as log_file:
            with tempfile.NamedTemporaryFile() as arg:
                sys.stdout = arg
                sys.stderr = arg
                ret_val = arg(*a, **ka)
                arg.flush()
                arg.seek(0)
                log_file.write('\n'.join(arg.readlines()))
                arg.flush()
                arg.seek(0)
                sys.__stdout__.write('\n'.join(arg.readlines()))
                sys.stdout = sys.__stdout__
                sys.stderr = sys.__stderr__
                return ret_val

    return wrapper


if __name__ == '__main__':
    @print_tmp_file
    def some_func(abc='Hello!!!'):
        ''' This is the docstring of the someFunc function. '''
        print abc
        return 1

    some_func('Print something here')

在上述代码上运行 pylint 会给出以下警告:

W:6,19:未使用的参数“arg”(未使用的参数)

这清楚地表明出了问题。

【讨论】:

  • 实际上,arg 不是文件。它是由装饰器包装的功能。使用def printUsingTempFile(arg): 时,retVal = f(*a, **ka) 应更改为retVal = arg(*a, **ka)。那是错误。这样,无论提供的函数打印到文件中,也会被记录。但是,最后我认为我真的需要研究 solamz 的 sugeston。我可能会为自己省去很多麻烦。
猜你喜欢
  • 2021-08-08
  • 1970-01-01
  • 2011-07-04
  • 2013-12-04
  • 2012-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-12
相关资源
最近更新 更多