我有一个第三方python控制台脚本,我不想修改该源代码.
但我想配置由脚本及其库完成的日志记录.该脚本使用标准的python日志记录,但不支持它的配置.
该脚本使用此模式:
import logging
logger=logging.getLogger(__name__)
Run Code Online (Sandbox Code Playgroud)
用例:
如果我不想修改控制台脚本的来源,我该如何配置日志记录?
该脚本通过调用cron.
如果此脚本如何配置日志记录?
在这个答案中创建一个包装器脚本对我来说不是一个解决方案.
linux进程层次结构如下所示:
Cron -> third_party_script
Run Code Online (Sandbox Code Playgroud)
在cron和third_party_script.之间应该有任何"胶水","包装"或"脏黑客"脚本.
我想练习"关注点分离".我希望能够在一个地方配置一次记录.这个配置应该被virtualenv的所有python代码使用.编写包装器将是一种解决方法.我想要一个解决方案.
库不应该配置日志记录 - 这取决于应用程序开发人员.Inbar Rose的回答并不完全正确.如果调用您所指的模块foo,则__name__其getLogger调用中的引用将被传入foo.因此,在您的配置代码中,您需要执行相应的操作
logging.getLogger('foo').setLevel(logging.WARNING)
Run Code Online (Sandbox Code Playgroud)
要在日志中包含PID,只需确保为Formatters使用适当的格式字符串,即包含的格式%(process)d.一个简单的例子是:
logging.basicConfig(format='%(process)d %(message)s')
Run Code Online (Sandbox Code Playgroud)
请注意,您无法同时从多个进程写入同一日志文件 - 如果要执行此操作,可能需要考虑其他方法.
更新:应用程序开发人员是编写Python代码的人,该代码不是库,而是由用户或其他脚本通过命令行或其他创建Python进程的方式调用.
要使用上面发布的代码,只要它是一个库,就不需要包装或修改第三方代码.例如,在调用第三方库的主脚本中:
if __name__ == '__main__':
# configure logging here
# sets the third party's logger to do WARNING or greater
# replace 'foo' with whatever the top-level package name your
# third party package uses
logging.getLogger('foo').setLevel(logging.WARNING)
# set any other loggers to use INFO or greater,
# unless otherwise configured explicitly
logging.basicConfig(level=logging.INFO, format='%(process)d %(message)s')
# now call the main function (or else inline code here)
main()
Run Code Online (Sandbox Code Playgroud)
如果第三方代码通过cron运行,那么它不是库代码 - 它是一个应用程序,你可能运气不好.
几个月前我问过这个问题.不幸的是,我没有得到满意的答案.
使用日志记录和设置它之间的区别对我来说很重要.
这是我的解决方案:在我们的上下文中,我们设置了一个被调用的方法中的日志记录usercustomize.py.
这样,可选插件可以使用日志记录而无需进行设置.
这几乎解决了我的所有需求.
到目前为止,我发现没有比这更好的方法usercustomize.py.我完美的解决方案是我会调用的virtualenvcustomize.py:如果解释器加载virtualenv,则会运行一些初始化代码.到目前为止,我找不到这样的钩子.如果您有解决方案,请告诉我.
几种可能性:
包装纸
如果您可以编辑您的cron表,您可以在python中创建一个小脚本来获取lib记录器,删除现有的日志处理程序并在其上挂钩您的自定义处理程序:
# Assumes the lib defines a logger object
from third_party_lib import *
# Note this assumes only one handler was defined by the lib
logger.removeHandler(logger.handlers[0])
# Then we can hook our custom format handler
custom_handler = logging.StreamHandler(sys.stdout)
custom_handler.setFormatter(logging.Formatter(format = '%(asctime)s %(levelname)s %(name)s %(process)d: %(message)s', None))
logger.addHandler(custom_handler)
logger.setLevel(logging.WARNING)
Run Code Online (Sandbox Code Playgroud)
另外请记住,假设lib没有在路上重新声明记录器.
动态代码编辑
如果您无法修改cron调用,则可以进行动态代码编辑,但这相当于手动编辑文件(hacky):
| 归档时间: |
|
| 查看次数: |
2779 次 |
| 最近记录: |