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

时间:2013-11-04 09:50:57

标签: python logging csv python-3.x

我想记录每个请求以格式化形式发送到繁忙的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 个答案:

答案 0 :(得分:9)

只需使用python的logging模块。

您可以按照自己的方式调整输出;看看Changing the format of displayed messages

  

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

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')

Formatters

  

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

您可以在此处找到可以使用的attribtus列表:LogRecord attributes


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

这是一个简单的例子:

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”,“所以应该”“这个”“,它正在引用......”   “警告”,“而且这也是”

答案 1 :(得分:3)

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

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

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 - write data into csv format as string (not file)

答案 2 :(得分:2)

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

答案 3 :(得分:0)

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

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