繁体   English   中英

在csv文件中记录的正确方法是什么?

[英]what is the proper way to do logging in csv file?

我想记录每个请求的一些信息以格式化的形式发送到繁忙的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)

因为它每次都会打开和关闭一个文件,我担心这样会降低整个服务器的性能,我该怎么办?

只需使用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') 

格式化程序

Formatter对象配置日志消息的最终顺序,结构和内容。

您可以在此处找到可以使用的attribtus列表: 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”,“所以应该”“这个”,并且它正在使用引用...“
“警告”,“这也是”

我同意你应该使用日志记录模块,但你不能像其他一些答案所显示的格式字符串那样正确地完成它,因为它们没有解决你记录包含逗号的消息的情况。

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

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格式为字符串(不是文件)

正如树懒建议的那样,您可以轻松地将日志的分隔符编辑为逗号,从而生成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.')

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

我再说一遍 - 这不是最好的主意,这是我想到的第一件事。 您可能希望参考Flask或其他一些webapp框架中的日志记录实现(AFAIR Flask也有CSV日志记录)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM