Optional keys in string formats using '%' operator?

微笑、不失礼 提交于 2020-01-25 20:38:27

问题


Is is possible to have optional keys in string formats using '%' operator? I’m using the logging API with Python 2.7, so I can't use Advanced String Formatting.

My problem is as follow:

>>> import logging

>>> FORMAT = '%(asctime)-15s %(message)s %(user)s'
>>> logging.basicConfig(format=FORMAT)

>>> logging.warning("It works for:", extra={'user': 'me'})
2016-08-29 11:24:31,262 It works for: me

>>> logging.warning("It does't work!")
Traceback (most recent call last):
  ...
KeyError: 'user'
Logged from file <input>, line 1

I want to have an empty string for user if missing. How can I do that?

I tried with a defaultdict, but it fails:

>>> import collections
>>> extra = collections.defaultdict(unicode)
>>> logging.warning("It does't work!", extra=extra)
Traceback (most recent call last):
  ...
KeyError: 'user'
Logged from file <input>, line 1

By contrast, with Jinja2, we can do:

>>> import jinja2
>>> jinja2.Template('name: {{ name }}, email: {{ email }}').render(name="me")
u'name: me, email: '

=> no exception here, just an empty string (for "email").


回答1:


A) The defaultdict approach works fine, but only if used directly.

>>> import collections
>>> dd=collections.defaultdict(str)
>>> dd['k'] = 22
>>> '%(k)s %(nn)s' % dd
'22 '

B) The extra argument to a log function is used as described in the docs, i.e. not directly as shown above. That's why using a defaultdict instead of a regular dict does not make a difference.

The third keyword argument is extra which can be used to pass a dictionary which is used to populate the dict of the LogRecord created for the logging event with user-defined attributes.


C) You can use a logging filter to take care of the missing extra data:

import logging

class UserFilter:
    def filter(self, record):
        try:
            record.user
        except AttributeError:
            record.user = '<N/A>'
        return True

FORMAT = '%(asctime)-15s %(message)s %(user)s'
logging.basicConfig(format=FORMAT)
logging.getLogger().addFilter(UserFilter())

logging.warning("It works for:", extra={'user': 'me'})

logging.warning("It doesn't work!")
# DATE TIME It doesn't work! <N/A>

Any class with a filter method is fine. It can modify the record in-place and it must return True for accepting the record or False for filtering it out.



来源:https://stackoverflow.com/questions/39203016/optional-keys-in-string-formats-using-operator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!