Logging

https://d33wubrfki0l68.cloudfront.net/4a9f1d4fbeff3b43baf2d5a2becc1f2688217a3c/83efa/_images/35254379756_c9fe23f843_k_d.jpg
The logging module has been a part of Python’s Standard Library sinceversion 2.3. It is succinctly described in PEP 282. The documentationis notoriously hard to read, except for the basic logging tutorial.

Logging serves two purposes:

  • Diagnostic logging records events related to the application’soperation. If a user calls in to report an error, for example, the logscan be searched for context.
  • Audit logging records events for business analysis. A user’stransactions can be extracted and combined with other user details forreports or to optimize a business goal.

… or Print?

The only time that print is a better option than logging is whenthe goal is to display a help statement for a command line application.Other reasons why logging is better than print:

  • The log record, which is created with every logging event, containsreadily available diagnostic information such as the file name, full path,function, and line number of the logging event.
  • Events logged in included modules are automatically accessible via the rootlogger to your application’s logging stream, unless you filter them out.
  • Logging can be selectively silenced by using the methodlogging.Logger.setLevel() or disabled by setting the attributelogging.Logger.disabled to True.

Logging in a Library

Notes for configuring logging for a library are in thelogging tutorial. Because the user, not the library, shoulddictate what happens when a logging event occurs, one admonition bearsrepeating:

Note

It is strongly advised that you do not add any handlers other thanNullHandler to your library’s loggers.

Best practice when instantiating loggers in a library is to only create themusing the name global variable: the logging module creates ahierarchy of loggers using dot notation, so using name ensuresno name collisions.

Here is an example of best practice from the requests source – placethis in your init.py:

  1. import logging
  2. logging.getLogger(__name__).addHandler(logging.NullHandler())

Logging in an Application

The twelve factor app, an authoritative referencefor good practice in application development, contains a section onlogging best practice. It emphaticallyadvocates for treating log events as an event stream, and forsending that event stream to standard output to be handled by theapplication environment.

There are at least three ways to configure a logger:

  • Using an INI-formatted file:
    • Pro: possible to update configuration while running using thefunction logging.config.listen() to listen on a socket.
    • Con: less control (e.g. custom subclassed filters or loggers)than possible when configuring a logger in code.
  • Using a dictionary or a JSON-formatted file:
    • Pro: in addition to updating while running, it is possible to loadfrom a file using the json module, in the standard library sincePython 2.6.
    • Con: less control than when configuring a logger in code.
  • Using code:
    • Pro: complete control over the configuration.
    • Con: modifications require a change to source code.

Example Configuration via an INI File

Let us say the file is named logging_config.ini.More details for the file format are in the logging configurationsection of the logging tutorial.

  1. [loggers]
  2. keys=root
  3.  
  4. [handlers]
  5. keys=stream_handler
  6.  
  7. [formatters]
  8. keys=formatter
  9.  
  10. [logger_root]
  11. level=DEBUG
  12. handlers=stream_handler
  13.  
  14. [handler_stream_handler]
  15. class=StreamHandler
  16. level=DEBUG
  17. formatter=formatter
  18. args=(sys.stderr,)
  19.  
  20. [formatter_formatter]
  21. format=%(asctime)s %(name)-12s %(levelname)-8s %(message)s

Then use logging.config.fileConfig() in the code:

  1. import logging
  2. from logging.config import fileConfig
  3.  
  4. fileConfig('logging_config.ini')
  5. logger = logging.getLogger()
  6. logger.debug('often makes a very good meal of %s', 'visiting tourists')

Example Configuration via a Dictionary

As of Python 2.7, you can use a dictionary with configuration details.PEP 391 contains a list of the mandatory and optional elements inthe configuration dictionary.

  1. import logging
  2. from logging.config import dictConfig
  3.  
  4. logging_config = dict(
  5. version = 1,
  6. formatters = {
  7. 'f': {'format':
  8. '%(asctime)s %(name)-12s %(levelname)-8s %(message)s'}
  9. },
  10. handlers = {
  11. 'h': {'class': 'logging.StreamHandler',
  12. 'formatter': 'f',
  13. 'level': logging.DEBUG}
  14. },
  15. root = {
  16. 'handlers': ['h'],
  17. 'level': logging.DEBUG,
  18. },
  19. )
  20.  
  21. dictConfig(logging_config)
  22.  
  23. logger = logging.getLogger()
  24. logger.debug('often makes a very good meal of %s', 'visiting tourists')

Example Configuration Directly in Code

  1. import logging
  2.  
  3. logger = logging.getLogger()
  4. handler = logging.StreamHandler()
  5. formatter = logging.Formatter(
  6. '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
  7. handler.setFormatter(formatter)
  8. logger.addHandler(handler)
  9. logger.setLevel(logging.DEBUG)
  10.  
  11. logger.debug('often makes a very good meal of %s', 'visiting tourists')

原文: https://docs.python-guide.org/writing/logging/