将Python输出写入屏幕或文件名

时间:2014-11-05 21:49:47

标签: python class logging

我正在编写一些代码,将日志输出到屏幕或文件,但不是两者。 我认为最简单的方法是编写一个类:

class WriteLog:
    "write to screen or to file"

    def __init__(self, stdout, filename):
        self.stdout = stdout
        self.logfile = file(filename, 'a')

    def write(self, text):
        self.stdout.write(text)
        self.logfile.write(text)

    def close(self):
        self.stdout.close()
        self.logfile.close()

然后称之为:

output = WriteLog(sys.stdout, 'log.txt')

但是,我不确定如何允许在两者之间切换,即类中应该有一个选项可以将WriteLog设置为使用stdout或filename。设置该选项后,我只需使用WriteLog,而无需if语句等。

有什么想法吗?我在网上看到的大多数解决方案都试图同时输出。

感谢。

4 个答案:

答案 0 :(得分:1)

我不是它的专家,但尝试使用logging library,也许你可以拥有2个处理程序的记录器,一个用于文件,一个用于流,然后动态添加/删除处理程序。

答案 1 :(得分:1)

也许是这样的?它使用符号名称'stdout''stderr'在构造函数中,或真正的文件名。 if的用法仅限于构造函数。顺便说一句,我认为你试图过早地优化(这是所有邪恶的根源):你在现实生活中试图节省if的时间,该程序将花费更多的时间在文件I / O;使if的潜在浪费可以忽略不计。

import sys

class WriteLog:

    def __init__(self, output):
        self.output = output
        if output == 'stdout':
            self.logfile = sys.stdout
        elif output == 'stderr':
            self.logfile = sys.stderr
        else:
            self.logfile = open(output, 'a')

    def write(self, text):
        self.logfile.write(text)

    def close(self):
        if self.output != 'stdout' and self.output != 'stderr':
            self.logfile.close()

    def __del__(self):
        self.close()

if __name__ == '__main__':
    a = WriteLog('stdout')
    a.write('This goes to stdout\n')
    b = WriteLog('stderr')
    b.write('This goes to stderr\n')
    c = WriteLog('/tmp/logfile')
    c.write('This goes to /tmp/logfile\n')

答案 2 :(得分:0)

我喜欢有关使用日志库的建议。但是如果你想自己破解某些东西,也许传递文件句柄是值得考虑的。

import sys

class WriteLog:
    "write to screen or to file"

    def __init__(self, output):
        self.output = output

    def write(self, text):
        self.output.write(text)

    def close(self):
        self.output.close()

logger = WriteLog(file('c:/temp/log.txt','a' ))
logger.write("I write to the log file.\n")
logger.close()

sysout = WriteLog(sys.stdout)
sysout.write("I write to the screen.\n")        

答案 3 :(得分:0)

您可以使用logging库来执行与此类似的操作。以下函数将在INFO级别设置日志记录对象。

def setup_logging(file_name, log_to_file=False, log_to_console=False ):
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)

    # Create Console handler
    if log_to_file:
        console_log = logging.StreamHandler()
        console_log.setLevel(logging.INFO)
        formatter = logging.Formatter('%(asctime)s - %(levelname)-8s - %(name)-12s - %(message)s')
        console_log.setFormatter(formatter)
        logger.addHandler(console_log)

    # Log file
    if log_to_console:
        file_log = logging.FileHandler('%s.log' % (file_name), 'a', encoding='UTF-8')
        file_log.setLevel(logging.INFO)
        formatter = logging.Formatter('%(asctime)s - %(levelname)-8s - %(name)-12s - %(message)s')
        file_log.setFormatter(formatter)
        logger.addHandler(file_log)

    return logger

您将日志的名称和您希望记录的位置(传递到文件,控制台或两者)传递给它。然后你可以在代码块中使用这个函数,如下所示:

logger = setup_logging("mylog.log", log_to_file=True, log_to_console=False)
logger.info('Message')

此示例将记录到名为mylog.log的文件(在当前目录中)并具有如下输出:

2014-11-05 17:20:29,933 - INFO     - root         - Message

此功能有待改进的地方(如果您想添加更多功能)。现在,它会在INFO行的日志级别.setLevel(logging.INFO)上记录到控制台和文件。如果您愿意,可以动态设置。

此外,就像现在一样,您可以轻松添加标准日志记录行(logger.debug('Message')logger.critcal('DANGER!'))而无需修改类。在这些示例中,调试消息不会打印(因为它设置为INFO)而关键的消息将会打印出来。