20

我想以格式化的形式记录发送到繁忙的 http 服务器的每个请求的一些信息,使用日志模块会创建一些我不想做的事情:

[I 131104 15:31:29 Sys:34]

我想到了 csv 格式,但我不知道如何自定义它,python 得到了 csv 模块,但请阅读手册

import csv
with open('some.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerows(someiterable)

由于每次都会打开和关闭一个文件,恐怕这样会降低整个服务器的性能,我该怎么办?

4

4 回答 4

22

只需使用python的logging模块。

您可以按照自己的方式调整输出;看看改变显示消息的格式

要更改用于显示消息的格式,您需要指定要使用的格式:

import logging
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)
logging.debug('This message should appear on the console')
logging.info('So should this')
logging.warning('And this, too')

格式化程序

格式化程序对象配置日志消息的最终顺序、结构和内容。

您将在此处找到可以使用的属性列表:LogRecord 属性


如果你想生成一个有效的 csv 文件,也可以使用 python 的csv模块

这是一个简单的例子:

import logging
import csv
import io

class CsvFormatter(logging.Formatter):
    def __init__(self):
        super().__init__()
        self.output = io.StringIO()
        self.writer = csv.writer(self.output, quoting=csv.QUOTE_ALL)

    def format(self, record):
        self.writer.writerow([record.levelname, record.msg])
        data = self.output.getvalue()
        self.output.truncate(0)
        self.output.seek(0)
        return data.strip()

logging.basicConfig(level=logging.DEBUG)

logger = logging.getLogger(__name__)
logging.root.handlers[0].setFormatter(CsvFormatter())

logger.debug('This message should appear on the console')
logger.info('So should "this", and it\'s using quoting...')
logger.warning('And this, too')

输出:

"DEBUG","这条消息应该出现在控制台上"
"INFO","""this"" 也应该出现,并且它正在使用引用..."
"WARNING","还有这个"

于 2013-11-04T10:46:10.917 回答
4

我同意您应该使用日志记录模块,但是您不能像其他一些答案显示的那样仅使用格式字符串来正确执行此操作,因为它们没有解决您记录包含逗号的消息的情况。

如果您需要一个能够正确转义消息(或其他字段,我想)中的任何特殊字符的解决方案,您将必须编写一个自定义格式化程序并设置它。

logger = logging.getLogger()

formatter = MyCsvFormatter()

handler = logging.FileHandler(filename, "w")
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(level)

您显然必须实现 MyCsvFormatter 类,该类应继承自 logging.Formatter 并覆盖 format() 方法

class MyCsvFormatter(logging.Formatter):
    def __init__(self):
        fmt = "%(levelname)s,%(message)s" # Set a format that uses commas, like the other answers
        super(MyCsvFormatter, self).__init__(fmt=fmt)

    def format(self, record):
        msg = record.getMessage()
        # convert msg to a csv compatible string using your method of choice
        record.msg = msg
        return super(MyCsvFormatter, self).format(self, record)

注意:我以前做过类似的事情,但没有测试过这个特定的代码示例

至于对消息进行实际转义,这是一种可能的方法: Python - 将数据写入 csv 格式作为字符串(不是文件)

于 2014-12-06T01:36:54.030 回答
4

正如树懒建议的那样,您可以轻松地将日志的分隔符编辑为逗号,从而生成一个 CSV 文件。

工作示例:

import logging

# create logger
lgr = logging.getLogger('logger name')
lgr.setLevel(logging.DEBUG) # log all escalated at and above DEBUG
# add a file handler
fh = logging.FileHandler('path_of_your_log.csv')
fh.setLevel(logging.DEBUG) # ensure all messages are logged to file

# create a formatter and set the formatter for the handler.
frmt = logging.Formatter('%(asctime)s,%(name)s,%(levelname)s,%(message)s')
fh.setFormatter(frmt)

# add the Handler to the logger
lgr.addHandler(fh)

# You can now start issuing logging statements in your code
lgr.debug('a debug message')
lgr.info('an info message')
lgr.warn('A Checkout this warning.')
lgr.error('An error writen here.')
lgr.critical('Something very critical happened.')
于 2014-05-30T18:55:55.227 回答
0

我认为这不是最好的主意,但它是可行的,而且非常简单。手动缓冲您的日志。将日志条目存储在某个地方,并不时将它们写入文件。如果您知道您的服务器将一直很忙,请在缓冲区达到一定大小时刷新缓冲区。如果在使用方面可能存在很大差距,我会说新线程(或更好的进程,检查自己为什么线程会吸收并减慢应用程序)具有无限(理论上当然)睡眠/刷新循环会更好。另外,请记住创建某种钩子,当服务器中断或失败时会刷新缓冲区(可能是信号?或者只是在 main 函数上尝试/除外 - 还有更多方法可以做到),这样你就不会丢失未刷新的缓冲区意外退出的数据。

我再说一遍——这不是最好的主意,这是我想到的第一件事。您可能想咨询 Flask 或其他一些 webapp 框架的日志实现(AFAIR Flask 也有 CSV 日志)。

于 2013-11-04T10:12:07.533 回答