简体   繁体   English

Python Requests库在日志记录中抛出异常

[英]Python Requests library throws exceptions in logging

The Python requests library appears to have some rather strange quirks when it comes to its logging behaviour. 当涉及到它的日志记录行为时,Python requests库似乎有一些相当奇怪的怪癖。 Using the latest Python 2.7.8, I have the following code: 使用最新的Python 2.7.8,我有以下代码:

import requests
import logging

logging.basicConfig(
    filename='mylog.txt',
    format='%(asctime)-19.19s|%(task)-36s|%(levelname)s:%(name)s: %(message)s',
    level=eval('logging.%s' % 'DEBUG'))

logger = logging.getLogger(__name__)

logger.info('myprogram starting up...', extra={'task': ''})     # so far so good
...
(ommited code)
...
payload = {'id': 'abc', 'status': 'ok'}

# At this point the program continues but throws an exception.
requests.get('http://localhost:9100/notify', params=payload) 

print 'Task is complete! NotifyURL was hit! - Exiting'

My program seems to exit normally, however inside the log file it creates (mylog.txt) I always find the following exception: 我的程序似乎正常退出,但是在它创建的日志文件中(mylog.txt)我总是发现以下异常:

KeyError: 'task'
Logged from file connectionpool.py, line 362

If I remove this: requests.get('http://localhost:9100/notify', params=payload) then the exception is gone. 如果我删除它: requests.get('http://localhost:9100/notify', params=payload)则异常消失。

What exactly am I doing wrong here and how may I fix this? 我到底做错了什么,我该如何解决这个问题? I am using requests v2.4.3. 我正在使用请求v2.4.3。

The problem is your custom logging format, where you expect a %(task) . 问题是您的自定义日志记录格式,您期望%(task) Requests (or rather the bundled urllib3) does not include the task parameter when logging, as it has no way of knowing, that you expect this. 请求(或者更确切地说是捆绑的urllib3)在记录时不包括task参数,因为它无法知道您期望这样做。

As indicated in t-8ch 's answer , the logger is being used internally by the requests library and this library doesn't know anything about your parameters. t-8ch回答所示 ,记录器正在由requests库内部使用,并且该库对您的参数一无所知。 A possible solution is to implant a custom filter in the library's logger (in this case, one of its modules): 一种可能的解决方案是在库的记录中植入自定义过滤器(在本例中为其中一个模块):

class TaskAddingFilter(logging.Filter):
    def __init__(self):
        logging.Filter.__init__(self)

    def filter(self, record):
        record.args = record.args + ('task', '')

# ...

requestsLogger = logging.getLogger('requests.packages.urllib3.connectionpool')
requestsLogger.addFilter(TaskAddingFilter())

Potentially, you need to add such filtering to all loggers from requests , which are: 您可能需要向requests所有记录器添加此类过滤,这些过滤器包括:

  • requests.packages.urllib3.util
  • requests.packages.urllib3.connectionpool
  • requests.packages
  • requests.packages.urllib3
  • requests.packages.urllib3.util.retry
  • requests
  • requests.packages.urllib3.poolmanager

in my version, you can find them using the logging.Logger.manager.loggerDict attribute. 在我的版本中,您可以使用logging.Logger.manager.loggerDict属性找到它们。 So, you could do something like this: 所以,你可以这样做:

for name,logger in logging.Logger.manager.loggerDict.iteritems():
    logger = logging.getLogger(name) # because of lazy initialization
    if name.startswith('requests.'):
        logger.addFilter(TaskAddingFilter())

The TaskAddingFilter can be a bit smarter of course, eg adding a particular task entry depending on where you are in your code. TaskAddingFilter可以更聪明一些,例如根据您在代码中的位置添加特定task条目。 I've added only the simplest solution for the code you've provided - the exception doesn't occur anymore - but the wide range of possibilities seems obvious ;) 我只为你提供的代码添加了最简单的解决方案 - 不再发生异常 - 但是各种各样的可能性似乎很明显;)

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

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