diff options
author | Vinay Sajip <vinay_sajip@yahoo.co.uk> | 2021-07-25 17:05:39 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-25 17:05:39 (GMT) |
commit | 9751f85914e0ef3324671a91da34a635d48b17fb (patch) | |
tree | 8b9f7c4a564d082dc4495ce5c08299d3501f6ccc /Doc/howto | |
parent | 50b72768ffe6413424dc4eba916dd1ff89a2fe7b (diff) | |
download | cpython-9751f85914e0ef3324671a91da34a635d48b17fb.zip cpython-9751f85914e0ef3324671a91da34a635d48b17fb.tar.gz cpython-9751f85914e0ef3324671a91da34a635d48b17fb.tar.bz2 |
bpo-44399: Update logging cookbook to document patterns to be avoided. (GH-27348)
Diffstat (limited to 'Doc/howto')
-rw-r--r-- | Doc/howto/logging-cookbook.rst | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst index 5777a4c..20b02c8 100644 --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -2979,3 +2979,82 @@ refer to the comments in the code snippet for more detailed information. if __name__=='__main__': main() + + +.. patterns-to-avoid: + +Patterns to avoid +----------------- + +Although the preceding sections have described ways of doing things you might +need to do or deal with, it is worth mentioning some usage patterns which are +*unhelpful*, and which should therefore be avoided in most cases. The following +sections are in no particular order. + + +Opening the same log file multiple times +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +On Windows, you will generally not be able to open the same file multiple times +as this will lead to a "file is in use by another process" error. However, on +POSIX platforms you'll not get any errors if you open the same file multiple +times. This could be done accidentally, for example by: + +* Adding a file handler more than once which references the same file (e.g. by + a copy/paste/forget-to-change error). + +* Opening two files that look different, as they have different names, but are + the same because one is a symbolic link to the other. + +* Forking a process, following which both parent and child have a reference to + the same file. This might be through use of the :mod:`multiprocessing` module, + for example. + +Opening a file multiple times might *appear* to work most of the time, but can +lead to a number of problems in practice: + +* Logging output can be garbled because multiple threads or processes try to + write to the same file. Although logging guards against concurrent use of the + same handler instance by multiple threads, there is no such protection if + concurrent writes are attempted by two different threads using two different + handler instances which happen to point to the same file. + +* An attempt to delete a file (e.g. during file rotation) silently fails, + because there is another reference pointing to it. This can lead to confusion + and wasted debugging time - log entries end up in unexpected places, or are + lost altogether. + +Use the techniques outlined in :ref:`multiple-processes` to circumvent such +issues. + +Using loggers as attributes in a class or passing them as parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +While there might be unusual cases where you'll need to do this, in general +there is no point because loggers are singletons. Code can always access a +given logger instance by name using ``logging.getLogger(name)``, so passing +instances around and holding them as instance attributes is pointless. Note +that in other languages such as Java and C#, loggers are often static class +attributes. However, this pattern doesn't make sense in Python, where the +module (and not the class) is the unit of software decomposition. + + +Adding handlers other than :class:`NullHandler` to a logger in a library +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Configuring logging by adding handlers, formatters and filters is the +responsibility of the application developer, not the library developer. If you +are maintaining a library, ensure that you don't add handlers to any of your +loggers other than a :class:`~logging.NullHandler` instance. + + +Creating a lot of loggers +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Loggers are singletons that are never freed during a script execution, and so +creating lots of loggers will use up memory which can't then be freed. Rather +than create a logger per e.g. file processed or network connection made, use +the :ref:`existing mechanisms <context-info>` for passing contextual +information into your logs and restrict the loggers created to those describing +areas within your application (generally modules, but occasionally slightly +more fine-grained than that). |