【问题标题】:Lazy evaluation of strings in python logging: comparing `%` with `.format`python日志记录中字符串的延迟评估:比较`%`和`.format`
【发布时间】:2019-01-31 09:54:44
【问题描述】:

这两个调用有什么区别:

import logging

logging.getLogger().debug('test: %i' % 42)

logging.getLogger().debug('test: {}'.format(42))

我们假设42 被转换为产生最终答案为 42 的字符串时,会被一些长时间的计算(比如 750 万年的计算)所取代。

如果日志记录设置为调试,第一种方法是否会延迟评估?

【问题讨论】:

  • 检查:stackoverflow.com/questions/40714555/…,为了性能,可能会想要比这些方法更快的f-strings,检查:stackoverflow.com/questions/43123408/f-strings-in-python-3-6
  • 超级有用的参考资料,感谢RafaelC,虽然它没有澄清懒惰的评估问题。
  • 在您的两个示例中,格式化的字符串在 logging 模块完全参与该过程之前由 Python 完全评估。您可能希望将格式字符串及其参数作为 单独的参数 传递给.debug(),以便它实际进行格式化 - 我假设它仅在消息不会出现时才这样做过滤掉了,但我不能 100% 确定这一点。
  • 如果你真的想要懒惰,你需要像if logging.getLogger().isEnabledFor(logging.DEBUG): … 这样的东西。但是,从您的 cmets 的答案来看,听起来您不需要那个。
  • 也许见stackoverflow.com/q/4148790/2864740。解决方案还显示了一个代理对象来推迟价值生成的成本。当然,生成调试值仍然应该“相对快速”和“无副作用”,否则启用调试的行为仍然会出现问题/出乎意料..

标签: python string logging


【解决方案1】:

两者都不懒惰。两个字符串在发送到记录器之前都被插值。 python 日志记录方面的延迟评估是使用单独的参数完成的。文档https://docs.python.org/2/library/logging.html 建议以下内容用于字符串插值的惰性求值;

logging.getLogger().debug('test: %i', 42)

TL;DR 在这种情况下,更容易考虑以下内容。我们向记录器发送了一个原始类型(字符串)但只有一个参数。所以不能偷懒。

【讨论】:

  • 请注意,在 Python 3.2+ 中,you can also do lazy evaluation with str.format style strings,尽管%-style 仍然是默认值。
  • 这仍然是 not lazy 在被问到的意义上:.debug('test: %i', takes_75_million_years_to_generate) - 它只是推迟创建 string 本身,而不是生成作为参数提供的值,相对而言无关紧要:}原始问题含糊不清“我们假设 42 被一些长时间计算(例如 750 万年)所取代,最终答案为 42。”,但是一旦产生了 42,成本已经支付
  • 原来的问题很模糊,我的错。我只是想询问字符串连接的评估。感谢您澄清这一点。
  • 我在原始问题中添加了“当转换为字符串时”以澄清这个细节。
【解决方案2】:

我会查看我在 cmets 中发布的参考资料,以获取有关 %.format() 的更多详细信息。

对于懒惰的评估问题,答案是

一个简单的测试就可以了

def func1(x):
    time.sleep(5)
    return(x)

def func2(x):
    #time.sleep(5)
    return(x)

%timeit 'debug1: %s' % func1(3)
5 s ± 1.31 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit 'debug2: {}'.format(func1(3))
5 s ± 1.45 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit 'debug1: %s' % func2(3)
297 ns ± 11.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit 'debug2: {}'.format(func2(3))
404 ns ± 4.56 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

.format(显然)和% 方法中,无论如何都会计算func()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多