Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python-使用.format进行日志记录会创建额外的CPU周期吗_Python_Python 3.x_Logging - Fatal编程技术网

Python-使用.format进行日志记录会创建额外的CPU周期吗

Python-使用.format进行日志记录会创建额外的CPU周期吗,python,python-3.x,logging,Python,Python 3.x,Logging,test.py 我上面有以下代码 当我使用python test.py-log=INFO执行时,是否真的会导致额外的CPU周期,因为它将首先格式化字符串,然后由于调试级别而不输出任何内容 是否仍然可以使用.format样式来记录日志,并且如果日志最终没有输出,就不会产生额外的CPU周期 编辑: 第1部分->是的,通过这个测试代码它是正确的,尽管非常小 old-format.py new-format.py python-mcprofile~/Desktop/old-format.py->5004

test.py

我上面有以下代码

当我使用python test.py-log=INFO执行时,是否真的会导致额外的CPU周期,因为它将首先格式化字符串,然后由于调试级别而不输出任何内容

是否仍然可以使用.format样式来记录日志,并且如果日志最终没有输出,就不会产生额外的CPU周期

编辑: 第1部分->是的,通过这个测试代码它是正确的,尽管非常小

old-format.py

new-format.py

python-mcprofile~/Desktop/old-format.py->500464函数调用只需0.176秒


python-mcprofile~/Desktop/new-format.py->600464函数调用只需0.237秒

是的,这样做时,它必须做额外的工作,创建永远不会使用的字符串。这就是说,一个小黑客将允许您切换到惰性格式的消息

Python人员提供了一个用于切换的方法,或者使用一个带有_str___________________________________________________。后一种方法在使用时是最干净的。《操作指南》中的简单示例如下:

import logging

class Message(object):
    def __init__(self, fmt, args):
        self.fmt = fmt
        self.args = args

    def __str__(self):
        return self.fmt.format(*self.args)

class StyleAdapter(logging.LoggerAdapter):
    def __init__(self, logger, extra=None):
        super(StyleAdapter, self).__init__(logger, extra or {})

    def log(self, level, msg, *args, **kwargs):
        if self.isEnabledFor(level):
            msg, kwargs = self.process(msg, kwargs)
            self.logger._log(level, Message(msg, args), (), **kwargs)

logger = StyleAdapter(logging.getLogger(__name__))

def main():
    logger.debug('Hello, {}', 'world!')

if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG)
    main()

在实际代码中,消息和样式适配器可能隐藏在单独的模块中,在使用它们的模块中只留下很少的自定义代码。

说真的,您担心的是错误的问题。是的,字符串将被格式化,可能最终会被丢弃。不,没关系

我怎么知道

你量过了吗?我打赌你没有,如果你有,你会发现格式化字符串的时间很短,数量级少于写入磁盘的时间,接近调用函数所需的时间

如果日志记录处于一个被称为数千次的紧密循环中,那么您的日志将很难看并且很难使用。所以我打赌它不在那里,或者在调试完成后不会在那里

如果日志记录不是在一个紧密的循环中,那么丢失消息的总格式化时间将是微乎其微的

如果程序是CPU密集型的,并且在Python解释器中花费了大量时间,那么日志不是原因。您需要寻找能够减轻解释器工作负担的Python技术/库,或者寻找能够减轻解释器工作负担的语言

如果日志模块的滥用是许多程序员非常担心的问题,那么文档中会有警告或代码中的修复。你有太多的公司独立发现了一个微不足道的优化问题

我见过使用重载调试日志的C程序,其中printf造成了很大的开销。但那是因为C的其余部分太少了。如果C具有垃圾收集、动态名称解析和列表理解等功能,格式化I/O将开始变得便宜


使用日志模块最有效的方式是最容易编程的方式,因为我希望您的时间!这不便宜。如果有人抱怨你浪费了周期,请他说明它如何占你程序运行时间的1%。然后你可以把注意力放在重要的事情上

为什么需要使用格式?是的,如果日志记录级别不相关,如果使用正确的方法,可以避免字符串插值。如果您担心这一分钟的CPU周期,那么您使用的语言是错误的。尝试C++或生锈,如果这是一个大的关注。@ TexEndiad它是一种解释性语言,所以我最好做一切在^ 2’。故意将其发挥到极致,但没有理由肆意使用运行时。字符串插值非常昂贵,而且在一个紧密的循环中可能会有大量调试消息。@roganjosh我同意您可以尽可能多地压缩性能,并在相同的环境中工作。。。如果他发现自己不得不担心很多这类事情,我只是提出一些建议。我根本不相信这种说法。我使用循环进行启发式,可能会运行30万次,直到问题得到解决。我可能想调试我在调度问题中所做的所有交换。循环使用python,转换使用numpy。您可以轻松地将调试消息的“我的运行时”翻倍。我基本上是站在你这边的,但当我知道python库适合我的应用程序时,我不喜欢横扫断言,但我不会故意放慢速度。@roganjosh,是的,日志消息可能会影响性能。不,你如何格式化它们并不重要。在300K循环中,是否生成调试语句?如果是的话,I/O比字符串格式更昂贵,而且格式是不可避免的,对吗?如果您没有,并且仍然在调用log函数,那么字符串格式化的成本占函数调用的百分比是多少?我是说:不多,所以没关系。
import logging

# V1
for x in range(0, 100000):
    logging.debug('%s before you %s', 'Look', 'leap!')
import logging

# V2
for x in range(0, 100000):
    logging.debug('{} before you {}'.format('Look', 'leap!'))
import logging

class Message(object):
    def __init__(self, fmt, args):
        self.fmt = fmt
        self.args = args

    def __str__(self):
        return self.fmt.format(*self.args)

class StyleAdapter(logging.LoggerAdapter):
    def __init__(self, logger, extra=None):
        super(StyleAdapter, self).__init__(logger, extra or {})

    def log(self, level, msg, *args, **kwargs):
        if self.isEnabledFor(level):
            msg, kwargs = self.process(msg, kwargs)
            self.logger._log(level, Message(msg, args), (), **kwargs)

logger = StyleAdapter(logging.getLogger(__name__))

def main():
    logger.debug('Hello, {}', 'world!')

if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG)
    main()