Logging documentation update.
This commit is contained in:
parent
31d04f2183
commit
9a6b400a59
|
@ -42,32 +42,33 @@ states, for each of a set of common tasks, the best tool to use for it.
|
||||||
+-------------------------------------+--------------------------------------+
|
+-------------------------------------+--------------------------------------+
|
||||||
| Task you want to perform | The best tool for the task |
|
| Task you want to perform | The best tool for the task |
|
||||||
+=====================================+======================================+
|
+=====================================+======================================+
|
||||||
| Display console output for ordinary | print() |
|
| Display console output for ordinary | :func:`print` |
|
||||||
| usage of a command line script or | |
|
| usage of a command line script or | |
|
||||||
| program | |
|
| program | |
|
||||||
+-------------------------------------+--------------------------------------+
|
+-------------------------------------+--------------------------------------+
|
||||||
| Report events that occur during | logging.info() (or logging.debug() |
|
| Report events that occur during | :func:`logging.info` (or |
|
||||||
| normal operation of a program (e.g. | for very detailed output for |
|
| normal operation of a program (e.g. | :func:`logging.debug` for very |
|
||||||
| for status monitoring or fault | diagnostic purposes) |
|
| for status monitoring or fault | detailed output for diagnostic |
|
||||||
| investigation) | |
|
| investigation) | purposes) |
|
||||||
+-------------------------------------+--------------------------------------+
|
+-------------------------------------+--------------------------------------+
|
||||||
| Issue a warning regarding a | warnings.warn() in library code |
|
| Issue a warning regarding a | :func:`warnings.warn` in library |
|
||||||
| particular runtime event | if the issue is avoidable and the |
|
| particular runtime event | code if the issue is avoidable and |
|
||||||
| | client application should be |
|
| | the client application should be |
|
||||||
| | modified to eliminate the warning |
|
| | modified to eliminate the warning |
|
||||||
| | |
|
| | |
|
||||||
| | logging.warn() if there is nothing |
|
| | :func:`logging.warning` if there is |
|
||||||
| | the client application can do about |
|
| | nothing the client application can do|
|
||||||
| | the situation, but the event should |
|
| | about the situation, but the event |
|
||||||
| | still be noted |
|
| | should still be noted |
|
||||||
+-------------------------------------+--------------------------------------+
|
+-------------------------------------+--------------------------------------+
|
||||||
| Report an error regarding a | Raise an exception |
|
| Report an error regarding a | Raise an exception |
|
||||||
| particular runtime event | |
|
| particular runtime event | |
|
||||||
+-------------------------------------+--------------------------------------+
|
+-------------------------------------+--------------------------------------+
|
||||||
| Report suppression of an error | logging.error(), logging.exception(),|
|
| Report suppression of an error | :func:`logging.error`, |
|
||||||
| without raising an exception (e.g. | or logging.critical() as appropriate |
|
| without raising an exception (e.g. | :func:`logging.exception` or |
|
||||||
| error handler in a long-running | for the specific error and |
|
| error handler in a long-running | :func:`logging.critical` as |
|
||||||
| server process) | application domain |
|
| server process) | appropriate for the specific error |
|
||||||
|
| | and application domain |
|
||||||
+-------------------------------------+--------------------------------------+
|
+-------------------------------------+--------------------------------------+
|
||||||
|
|
||||||
The logging functions are named after the level or severity of the events
|
The logging functions are named after the level or severity of the events
|
||||||
|
@ -85,7 +86,7 @@ described below (in increasing order of severity):
|
||||||
+--------------+---------------------------------------------+
|
+--------------+---------------------------------------------+
|
||||||
| ``WARNING`` | An indication that something unexpected |
|
| ``WARNING`` | An indication that something unexpected |
|
||||||
| | happened, or indicative of some problem in |
|
| | happened, or indicative of some problem in |
|
||||||
| | the near future (e.g. "disk space low"). |
|
| | the near future (e.g. 'disk space low'). |
|
||||||
| | The software is still working as expected. |
|
| | The software is still working as expected. |
|
||||||
+--------------+---------------------------------------------+
|
+--------------+---------------------------------------------+
|
||||||
| ``ERROR`` | Due to a more serious problem, the software |
|
| ``ERROR`` | Due to a more serious problem, the software |
|
||||||
|
@ -214,7 +215,7 @@ could organize logging in it::
|
||||||
def do_something():
|
def do_something():
|
||||||
logging.info('Doing something')
|
logging.info('Doing something')
|
||||||
|
|
||||||
If you run myapp.py, you should see this in myapp.log::
|
If you run *myapp.py*, you should see this in *myapp.log*::
|
||||||
|
|
||||||
INFO:root:Started
|
INFO:root:Started
|
||||||
INFO:root:Doing something
|
INFO:root:Doing something
|
||||||
|
@ -279,7 +280,7 @@ described in the next section.
|
||||||
Displaying the date/time in messages
|
Displaying the date/time in messages
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
To display the date and time of an event, you would place "%(asctime)s" in
|
To display the date and time of an event, you would place '%(asctime)s' in
|
||||||
your format string::
|
your format string::
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
@ -337,17 +338,20 @@ More advanced logging
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
The logging library takes a modular approach and offers several categories
|
The logging library takes a modular approach and offers several categories
|
||||||
of components: loggers, handlers, filters, and formatters. Loggers expose the
|
of components: loggers, handlers, filters, and formatters.
|
||||||
interface that application code directly uses. Handlers send the log records
|
|
||||||
(created by loggers) to the appropriate destination. Filters provide a finer
|
* Loggers expose the interface that application code directly uses.
|
||||||
grained facility for determining which log records to output. Formatters
|
* Handlers send the log records (created by loggers) to the appropriate
|
||||||
specify the layout of the resultant log record in the final output.
|
destination.
|
||||||
|
* Filters provide a finer grained facility for determining which log records
|
||||||
|
to output.
|
||||||
|
* Formatters specify the layout of log records in the final output.
|
||||||
|
|
||||||
Logging is performed by calling methods on instances of the :class:`Logger`
|
Logging is performed by calling methods on instances of the :class:`Logger`
|
||||||
class (hereafter called :dfn:`loggers`). Each instance has a name, and they are
|
class (hereafter called :dfn:`loggers`). Each instance has a name, and they are
|
||||||
conceptually arranged in a namespace hierarchy using dots (periods) as
|
conceptually arranged in a namespace hierarchy using dots (periods) as
|
||||||
separators. For example, a logger named "scan" is the parent of loggers
|
separators. For example, a logger named 'scan' is the parent of loggers
|
||||||
"scan.text", "scan.html" and "scan.pdf". Logger names can be anything you want,
|
'scan.text', 'scan.html' and 'scan.pdf'. Logger names can be anything you want,
|
||||||
and indicate the area of an application in which a logged message originates.
|
and indicate the area of an application in which a logged message originates.
|
||||||
|
|
||||||
A good convention to use when naming loggers is to use a module-level logger,
|
A good convention to use when naming loggers is to use a module-level logger,
|
||||||
|
@ -365,11 +369,11 @@ the root logger. The functions and the methods have the same signatures. The
|
||||||
root logger's name is printed as 'root' in the logged output.
|
root logger's name is printed as 'root' in the logged output.
|
||||||
|
|
||||||
It is, of course, possible to log messages to different destinations. Support
|
It is, of course, possible to log messages to different destinations. Support
|
||||||
for writing log messages to files, HTTP GET/POST locations, email via SMTP,
|
is included in the package for writing log messages to files, HTTP GET/POST
|
||||||
generic sockets, or OS-specific logging mechanisms is included in the package.
|
locations, email via SMTP, generic sockets, queues, or OS-specific logging
|
||||||
Destinations are served by :dfn:`handler` classes. You can create your own log
|
mechanisms such as syslog or the Windows NT event log. Destinations are served
|
||||||
destination class if you have special requirements not met by any of the
|
by :dfn:`handler` classes. You can create your own log destination class if
|
||||||
built-in handler classes.
|
you have special requirements not met by any of the built-in handler classes.
|
||||||
|
|
||||||
By default, no destination is set for any logging messages. You can specify
|
By default, no destination is set for any logging messages. You can specify
|
||||||
a destination (such as console or file) by using :func:`basicConfig` as in the
|
a destination (such as console or file) by using :func:`basicConfig` as in the
|
||||||
|
@ -537,7 +541,7 @@ The following message format string will log the time in a human-readable
|
||||||
format, the severity of the message, and the contents of the message, in that
|
format, the severity of the message, and the contents of the message, in that
|
||||||
order::
|
order::
|
||||||
|
|
||||||
"%(asctime)s - %(levelname)s - %(message)s"
|
'%(asctime)s - %(levelname)s - %(message)s'
|
||||||
|
|
||||||
Formatters use a user-configurable function to convert the creation time of a
|
Formatters use a user-configurable function to convert the creation time of a
|
||||||
record to a tuple. By default, :func:`time.localtime` is used; to change this
|
record to a tuple. By default, :func:`time.localtime` is used; to change this
|
||||||
|
@ -566,7 +570,7 @@ handler, and a simple formatter using Python code::
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
# create logger
|
# create logger
|
||||||
logger = logging.getLogger("simple_example")
|
logger = logging.getLogger('simple_example')
|
||||||
logger.setLevel(logging.DEBUG)
|
logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
# create console handler and set level to debug
|
# create console handler and set level to debug
|
||||||
|
@ -574,7 +578,7 @@ handler, and a simple formatter using Python code::
|
||||||
ch.setLevel(logging.DEBUG)
|
ch.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
# create formatter
|
# create formatter
|
||||||
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||||
|
|
||||||
# add formatter to ch
|
# add formatter to ch
|
||||||
ch.setFormatter(formatter)
|
ch.setFormatter(formatter)
|
||||||
|
@ -582,12 +586,12 @@ handler, and a simple formatter using Python code::
|
||||||
# add ch to logger
|
# add ch to logger
|
||||||
logger.addHandler(ch)
|
logger.addHandler(ch)
|
||||||
|
|
||||||
# "application" code
|
# 'application' code
|
||||||
logger.debug("debug message")
|
logger.debug('debug message')
|
||||||
logger.info("info message")
|
logger.info('info message')
|
||||||
logger.warn("warn message")
|
logger.warn('warn message')
|
||||||
logger.error("error message")
|
logger.error('error message')
|
||||||
logger.critical("critical message")
|
logger.critical('critical message')
|
||||||
|
|
||||||
Running this module from the command line produces the following output::
|
Running this module from the command line produces the following output::
|
||||||
|
|
||||||
|
@ -605,17 +609,17 @@ the names of the objects::
|
||||||
import logging
|
import logging
|
||||||
import logging.config
|
import logging.config
|
||||||
|
|
||||||
logging.config.fileConfig("logging.conf")
|
logging.config.fileConfig('logging.conf')
|
||||||
|
|
||||||
# create logger
|
# create logger
|
||||||
logger = logging.getLogger("simpleExample")
|
logger = logging.getLogger('simpleExample')
|
||||||
|
|
||||||
# "application" code
|
# 'application' code
|
||||||
logger.debug("debug message")
|
logger.debug('debug message')
|
||||||
logger.info("info message")
|
logger.info('info message')
|
||||||
logger.warn("warn message")
|
logger.warn('warn message')
|
||||||
logger.error("error message")
|
logger.error('error message')
|
||||||
logger.critical("critical message")
|
logger.critical('critical message')
|
||||||
|
|
||||||
Here is the logging.conf file::
|
Here is the logging.conf file::
|
||||||
|
|
||||||
|
@ -720,11 +724,11 @@ For versions of Python prior to 3.2, the behaviour is as follows:
|
||||||
silently dropped.
|
silently dropped.
|
||||||
|
|
||||||
* If *logging.raiseExceptions* is *True* (development mode), a message
|
* If *logging.raiseExceptions* is *True* (development mode), a message
|
||||||
"No handlers could be found for logger X.Y.Z" is printed once.
|
'No handlers could be found for logger X.Y.Z' is printed once.
|
||||||
|
|
||||||
In Python 3.2 and later, the behaviour is as follows:
|
In Python 3.2 and later, the behaviour is as follows:
|
||||||
|
|
||||||
* The event is output using a 'handler of last resort", stored in
|
* The event is output using a 'handler of last resort', stored in
|
||||||
``logging.lastResort``. This internal handler is not associated with any
|
``logging.lastResort``. This internal handler is not associated with any
|
||||||
logger, and acts like a :class:`StreamHandler` which writes the event
|
logger, and acts like a :class:`StreamHandler` which writes the event
|
||||||
description message to the current value of ``sys.stderr`` (therefore
|
description message to the current value of ``sys.stderr`` (therefore
|
||||||
|
@ -776,7 +780,7 @@ than* :class:`NullHandler` *to your library's loggers*. This is because the
|
||||||
configuration of handlers is the prerogative of the application developer who
|
configuration of handlers is the prerogative of the application developer who
|
||||||
uses your library. The application developer knows their target audience and
|
uses your library. The application developer knows their target audience and
|
||||||
what handlers are most appropriate for their application: if you add handlers
|
what handlers are most appropriate for their application: if you add handlers
|
||||||
"under the hood", you might well interfere with their ability to carry out
|
'under the hood', you might well interfere with their ability to carry out
|
||||||
unit tests and deliver logs which suit their requirements.
|
unit tests and deliver logs which suit their requirements.
|
||||||
|
|
||||||
|
|
||||||
|
@ -910,8 +914,8 @@ provided:
|
||||||
.. currentmodule:: logging
|
.. currentmodule:: logging
|
||||||
|
|
||||||
#. :class:`NullHandler` instances do nothing with error messages. They are used
|
#. :class:`NullHandler` instances do nothing with error messages. They are used
|
||||||
by library developers who want to use logging, but want to avoid the "No
|
by library developers who want to use logging, but want to avoid the 'No
|
||||||
handlers could be found for logger XXX" message which can be displayed if
|
handlers could be found for logger XXX' message which can be displayed if
|
||||||
the library user has not configured logging. See :ref:`library-config` for
|
the library user has not configured logging. See :ref:`library-config` for
|
||||||
more information.
|
more information.
|
||||||
|
|
||||||
|
@ -957,7 +961,7 @@ functions.
|
||||||
|
|
||||||
Return a logger with the specified name or, if name is ``None``, return a
|
Return a logger with the specified name or, if name is ``None``, return a
|
||||||
logger which is the root logger of the hierarchy. If specified, the name is
|
logger which is the root logger of the hierarchy. If specified, the name is
|
||||||
typically a dot-separated hierarchical name like *"a"*, *"a.b"* or *"a.b.c.d"*.
|
typically a dot-separated hierarchical name like *'a'*, *'a.b'* or *'a.b.c.d'*.
|
||||||
Choice of these names is entirely up to the developer who is using logging.
|
Choice of these names is entirely up to the developer who is using logging.
|
||||||
|
|
||||||
All calls to this function with a given name return the same logger instance.
|
All calls to this function with a given name return the same logger instance.
|
||||||
|
@ -1025,10 +1029,10 @@ functions.
|
||||||
be used as you like. For example, they could be incorporated into logged
|
be used as you like. For example, they could be incorporated into logged
|
||||||
messages. For example::
|
messages. For example::
|
||||||
|
|
||||||
FORMAT = "%(asctime)-15s %(clientip)s %(user)-8s %(message)s"
|
FORMAT = '%(asctime)-15s %(clientip)s %(user)-8s %(message)s'
|
||||||
logging.basicConfig(format=FORMAT)
|
logging.basicConfig(format=FORMAT)
|
||||||
d = {'clientip': '192.168.0.1', 'user': 'fbloggs'}
|
d = {'clientip': '192.168.0.1', 'user': 'fbloggs'}
|
||||||
logging.warning("Protocol problem: %s", "connection reset", extra=d)
|
logging.warning('Protocol problem: %s', 'connection reset', extra=d)
|
||||||
|
|
||||||
would print something like::
|
would print something like::
|
||||||
|
|
||||||
|
@ -1130,7 +1134,7 @@ functions.
|
||||||
have associated levels with names using :func:`addLevelName` then the name you
|
have associated levels with names using :func:`addLevelName` then the name you
|
||||||
have associated with *lvl* is returned. If a numeric value corresponding to one
|
have associated with *lvl* is returned. If a numeric value corresponding to one
|
||||||
of the defined levels is passed in, the corresponding string representation is
|
of the defined levels is passed in, the corresponding string representation is
|
||||||
returned. Otherwise, the string "Level %s" % lvl is returned.
|
returned. Otherwise, the string 'Level %s' % lvl is returned.
|
||||||
|
|
||||||
|
|
||||||
.. function:: makeLogRecord(attrdict)
|
.. function:: makeLogRecord(attrdict)
|
||||||
|
@ -1225,7 +1229,7 @@ functions.
|
||||||
|
|
||||||
The factory has the following signature:
|
The factory has the following signature:
|
||||||
|
|
||||||
``factory(name, level, fn, lno, msg, args, exc_info, func=None, sinfo=None, \*\*kwargs)``
|
``factory(name, level, fn, lno, msg, args, exc_info, func=None, sinfo=None, **kwargs)``
|
||||||
|
|
||||||
:name: The logger name.
|
:name: The logger name.
|
||||||
:level: The logging level (numeric).
|
:level: The logging level (numeric).
|
||||||
|
@ -1279,7 +1283,7 @@ instantiated directly, but always through the module-level function
|
||||||
the root logger, or delegation to the parent when the logger is a non-root
|
the root logger, or delegation to the parent when the logger is a non-root
|
||||||
logger). Note that the root logger is created with level :const:`WARNING`.
|
logger). Note that the root logger is created with level :const:`WARNING`.
|
||||||
|
|
||||||
The term "delegation to the parent" means that if a logger has a level of
|
The term 'delegation to the parent' means that if a logger has a level of
|
||||||
NOTSET, its chain of ancestor loggers is traversed until either an ancestor with
|
NOTSET, its chain of ancestor loggers is traversed until either an ancestor with
|
||||||
a level other than NOTSET is found, or the root is reached.
|
a level other than NOTSET is found, or the root is reached.
|
||||||
|
|
||||||
|
@ -1355,11 +1359,11 @@ instantiated directly, but always through the module-level function
|
||||||
be used as you like. For example, they could be incorporated into logged
|
be used as you like. For example, they could be incorporated into logged
|
||||||
messages. For example::
|
messages. For example::
|
||||||
|
|
||||||
FORMAT = "%(asctime)-15s %(clientip)s %(user)-8s %(message)s"
|
FORMAT = '%(asctime)-15s %(clientip)s %(user)-8s %(message)s'
|
||||||
logging.basicConfig(format=FORMAT)
|
logging.basicConfig(format=FORMAT)
|
||||||
d = { 'clientip' : '192.168.0.1', 'user' : 'fbloggs' }
|
d = { 'clientip' : '192.168.0.1', 'user' : 'fbloggs' }
|
||||||
logger = logging.getLogger("tcpserver")
|
logger = logging.getLogger('tcpserver')
|
||||||
logger.warning("Protocol problem: %s", "connection reset", extra=d)
|
logger.warning('Protocol problem: %s', 'connection reset', extra=d)
|
||||||
|
|
||||||
would print something like ::
|
would print something like ::
|
||||||
|
|
||||||
|
@ -1475,7 +1479,7 @@ instantiated directly, but always through the module-level function
|
||||||
Checks to see if this logger has any handlers configured. This is done by
|
Checks to see if this logger has any handlers configured. This is done by
|
||||||
looking for handlers in this logger and its parents in the logger hierarchy.
|
looking for handlers in this logger and its parents in the logger hierarchy.
|
||||||
Returns True if a handler was found, else False. The method stops searching
|
Returns True if a handler was found, else False. The method stops searching
|
||||||
up the hierarchy whenever a logger with the "propagate" attribute set to
|
up the hierarchy whenever a logger with the 'propagate' attribute set to
|
||||||
False is found - that will be the last logger which is checked for the
|
False is found - that will be the last logger which is checked for the
|
||||||
existence of handlers.
|
existence of handlers.
|
||||||
|
|
||||||
|
@ -1549,7 +1553,7 @@ documentation.
|
||||||
+-------------------+-----------------------------------------------+
|
+-------------------+-----------------------------------------------+
|
||||||
| ``%(asctime)s`` | Human-readable time when the |
|
| ``%(asctime)s`` | Human-readable time when the |
|
||||||
| | :class:`LogRecord` was created. By default |
|
| | :class:`LogRecord` was created. By default |
|
||||||
| | this is of the form "2003-07-08 16:49:45,896" |
|
| | this is of the form '2003-07-08 16:49:45,896' |
|
||||||
| | (the numbers after the comma are millisecond |
|
| | (the numbers after the comma are millisecond |
|
||||||
| | portion of the time). |
|
| | portion of the time). |
|
||||||
+-------------------+-----------------------------------------------+
|
+-------------------+-----------------------------------------------+
|
||||||
|
@ -1705,7 +1709,7 @@ show up at different levels::
|
||||||
You will notice that these log messages all have ``root`` embedded in them. The
|
You will notice that these log messages all have ``root`` embedded in them. The
|
||||||
logging module supports a hierarchy of loggers with different names. An easy
|
logging module supports a hierarchy of loggers with different names. An easy
|
||||||
way to tell where a specific log message comes from is to use a separate logger
|
way to tell where a specific log message comes from is to use a separate logger
|
||||||
object for each of your modules. Each new logger "inherits" the configuration
|
object for each of your modules. Each new logger 'inherits' the configuration
|
||||||
of its parent, and log messages sent to a logger include the name of that
|
of its parent, and log messages sent to a logger include the name of that
|
||||||
logger. Optionally, each logger can be configured differently, so that messages
|
logger. Optionally, each logger can be configured differently, so that messages
|
||||||
from different modules are handled in different ways. Let's look at a simple
|
from different modules are handled in different ways. Let's look at a simple
|
||||||
|
@ -1873,11 +1877,11 @@ information is added to the logging output. It's passed the message and
|
||||||
keyword arguments of the logging call, and it passes back (potentially)
|
keyword arguments of the logging call, and it passes back (potentially)
|
||||||
modified versions of these to use in the call to the underlying logger. The
|
modified versions of these to use in the call to the underlying logger. The
|
||||||
default implementation of this method leaves the message alone, but inserts
|
default implementation of this method leaves the message alone, but inserts
|
||||||
an "extra" key in the keyword argument whose value is the dict-like object
|
an 'extra' key in the keyword argument whose value is the dict-like object
|
||||||
passed to the constructor. Of course, if you had passed an "extra" keyword
|
passed to the constructor. Of course, if you had passed an 'extra' keyword
|
||||||
argument in the call to the adapter, it will be silently overwritten.
|
argument in the call to the adapter, it will be silently overwritten.
|
||||||
|
|
||||||
The advantage of using "extra" is that the values in the dict-like object are
|
The advantage of using 'extra' is that the values in the dict-like object are
|
||||||
merged into the :class:`LogRecord` instance's __dict__, allowing you to use
|
merged into the :class:`LogRecord` instance's __dict__, allowing you to use
|
||||||
customized strings with your :class:`Formatter` instances which know about
|
customized strings with your :class:`Formatter` instances which know about
|
||||||
the keys of the dict-like object. If you need a different method, e.g. if you
|
the keys of the dict-like object. If you need a different method, e.g. if you
|
||||||
|
@ -1885,7 +1889,7 @@ want to prepend or append the contextual information to the message string,
|
||||||
you just need to subclass :class:`LoggerAdapter` and override :meth:`process`
|
you just need to subclass :class:`LoggerAdapter` and override :meth:`process`
|
||||||
to do what you need. Here's an example script which uses this class, which
|
to do what you need. Here's an example script which uses this class, which
|
||||||
also illustrates what dict-like behaviour is needed from an arbitrary
|
also illustrates what dict-like behaviour is needed from an arbitrary
|
||||||
"dict-like" object for use in the constructor::
|
'dict-like' object for use in the constructor::
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
@ -1900,12 +1904,12 @@ also illustrates what dict-like behaviour is needed from an arbitrary
|
||||||
To allow this instance to look like a dict.
|
To allow this instance to look like a dict.
|
||||||
"""
|
"""
|
||||||
from random import choice
|
from random import choice
|
||||||
if name == "ip":
|
if name == 'ip':
|
||||||
result = choice(["127.0.0.1", "192.168.0.1"])
|
result = choice(['127.0.0.1', '192.168.0.1'])
|
||||||
elif name == "user":
|
elif name == 'user':
|
||||||
result = choice(["jim", "fred", "sheila"])
|
result = choice(['jim', 'fred', 'sheila'])
|
||||||
else:
|
else:
|
||||||
result = self.__dict__.get(name, "?")
|
result = self.__dict__.get(name, '?')
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
|
@ -1913,24 +1917,24 @@ also illustrates what dict-like behaviour is needed from an arbitrary
|
||||||
To allow iteration over keys, which will be merged into
|
To allow iteration over keys, which will be merged into
|
||||||
the LogRecord dict before formatting and output.
|
the LogRecord dict before formatting and output.
|
||||||
"""
|
"""
|
||||||
keys = ["ip", "user"]
|
keys = ['ip', 'user']
|
||||||
keys.extend(self.__dict__.keys())
|
keys.extend(self.__dict__.keys())
|
||||||
return keys.__iter__()
|
return keys.__iter__()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == '__main__':
|
||||||
from random import choice
|
from random import choice
|
||||||
levels = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL)
|
levels = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL)
|
||||||
a1 = logging.LoggerAdapter(logging.getLogger("a.b.c"),
|
a1 = logging.LoggerAdapter(logging.getLogger('a.b.c'),
|
||||||
{ "ip" : "123.231.231.123", "user" : "sheila" })
|
{ 'ip' : '123.231.231.123', 'user' : 'sheila' })
|
||||||
logging.basicConfig(level=logging.DEBUG,
|
logging.basicConfig(level=logging.DEBUG,
|
||||||
format="%(asctime)-15s %(name)-5s %(levelname)-8s IP: %(ip)-15s User: %(user)-8s %(message)s")
|
format='%(asctime)-15s %(name)-5s %(levelname)-8s IP: %(ip)-15s User: %(user)-8s %(message)s')
|
||||||
a1.debug("A debug message")
|
a1.debug('A debug message')
|
||||||
a1.info("An info message with %s", "some parameters")
|
a1.info('An info message with %s', 'some parameters')
|
||||||
a2 = logging.LoggerAdapter(logging.getLogger("d.e.f"), ConnInfo())
|
a2 = logging.LoggerAdapter(logging.getLogger('d.e.f'), ConnInfo())
|
||||||
for x in range(10):
|
for x in range(10):
|
||||||
lvl = choice(levels)
|
lvl = choice(levels)
|
||||||
lvlname = logging.getLevelName(lvl)
|
lvlname = logging.getLevelName(lvl)
|
||||||
a2.log(lvl, "A message at %s level with %d %s", lvlname, 2, "parameters")
|
a2.log(lvl, 'A message at %s level with %d %s', lvlname, 2, 'parameters')
|
||||||
|
|
||||||
When this script is run, the output should look something like this::
|
When this script is run, the output should look something like this::
|
||||||
|
|
||||||
|
@ -1987,24 +1991,24 @@ script::
|
||||||
record.user = choice(ContextFilter.USERS)
|
record.user = choice(ContextFilter.USERS)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == '__main__':
|
||||||
levels = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL)
|
levels = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL)
|
||||||
a1 = logging.LoggerAdapter(logging.getLogger("a.b.c"),
|
a1 = logging.LoggerAdapter(logging.getLogger('a.b.c'),
|
||||||
{ "ip" : "123.231.231.123", "user" : "sheila" })
|
{ 'ip' : '123.231.231.123', 'user' : 'sheila' })
|
||||||
logging.basicConfig(level=logging.DEBUG,
|
logging.basicConfig(level=logging.DEBUG,
|
||||||
format="%(asctime)-15s %(name)-5s %(levelname)-8s IP: %(ip)-15s User: %(user)-8s %(message)s")
|
format='%(asctime)-15s %(name)-5s %(levelname)-8s IP: %(ip)-15s User: %(user)-8s %(message)s')
|
||||||
a1 = logging.getLogger("a.b.c")
|
a1 = logging.getLogger('a.b.c')
|
||||||
a2 = logging.getLogger("d.e.f")
|
a2 = logging.getLogger('d.e.f')
|
||||||
|
|
||||||
f = ContextFilter()
|
f = ContextFilter()
|
||||||
a1.addFilter(f)
|
a1.addFilter(f)
|
||||||
a2.addFilter(f)
|
a2.addFilter(f)
|
||||||
a1.debug("A debug message")
|
a1.debug('A debug message')
|
||||||
a1.info("An info message with %s", "some parameters")
|
a1.info('An info message with %s', 'some parameters')
|
||||||
for x in range(10):
|
for x in range(10):
|
||||||
lvl = choice(levels)
|
lvl = choice(levels)
|
||||||
lvlname = logging.getLevelName(lvl)
|
lvlname = logging.getLevelName(lvl)
|
||||||
a2.log(lvl, "A message at %s level with %d %s", lvlname, 2, "parameters")
|
a2.log(lvl, 'A message at %s level with %d %s', lvlname, 2, 'parameters')
|
||||||
|
|
||||||
which, when run, produces something like::
|
which, when run, produces something like::
|
||||||
|
|
||||||
|
@ -2231,7 +2235,7 @@ module. Here is a basic working example::
|
||||||
chunk = self.connection.recv(4)
|
chunk = self.connection.recv(4)
|
||||||
if len(chunk) < 4:
|
if len(chunk) < 4:
|
||||||
break
|
break
|
||||||
slen = struct.unpack(">L", chunk)[0]
|
slen = struct.unpack('>L', chunk)[0]
|
||||||
chunk = self.connection.recv(slen)
|
chunk = self.connection.recv(slen)
|
||||||
while len(chunk) < slen:
|
while len(chunk) < slen:
|
||||||
chunk = chunk + self.connection.recv(slen - len(chunk))
|
chunk = chunk + self.connection.recv(slen - len(chunk))
|
||||||
|
@ -2257,7 +2261,8 @@ module. Here is a basic working example::
|
||||||
logger.handle(record)
|
logger.handle(record)
|
||||||
|
|
||||||
class LogRecordSocketReceiver(socketserver.ThreadingTCPServer):
|
class LogRecordSocketReceiver(socketserver.ThreadingTCPServer):
|
||||||
"""simple TCP socket-based logging receiver suitable for testing.
|
"""
|
||||||
|
Simple TCP socket-based logging receiver suitable for testing.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
allow_reuse_address = 1
|
allow_reuse_address = 1
|
||||||
|
@ -2283,12 +2288,12 @@ module. Here is a basic working example::
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
format="%(relativeCreated)5d %(name)-15s %(levelname)-8s %(message)s")
|
format='%(relativeCreated)5d %(name)-15s %(levelname)-8s %(message)s')
|
||||||
tcpserver = LogRecordSocketReceiver()
|
tcpserver = LogRecordSocketReceiver()
|
||||||
print("About to start TCP server...")
|
print('About to start TCP server...')
|
||||||
tcpserver.serve_until_stopped()
|
tcpserver.serve_until_stopped()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
||||||
First run the server, and then the client. On the client side, nothing is
|
First run the server, and then the client. On the client side, nothing is
|
||||||
|
@ -2395,7 +2400,7 @@ method which takes a level argument and returns true if the event would be
|
||||||
created by the Logger for that level of call. You can write code like this::
|
created by the Logger for that level of call. You can write code like this::
|
||||||
|
|
||||||
if logger.isEnabledFor(logging.DEBUG):
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
logger.debug("Message with %s, %s", expensive_func1(),
|
logger.debug('Message with %s, %s', expensive_func1(),
|
||||||
expensive_func2())
|
expensive_func2())
|
||||||
|
|
||||||
so that if the logger's threshold is set above ``DEBUG``, the calls to
|
so that if the logger's threshold is set above ``DEBUG``, the calls to
|
||||||
|
@ -2563,7 +2568,7 @@ and :meth:`flush` methods).
|
||||||
|
|
||||||
.. versionchanged:: 3.2
|
.. versionchanged:: 3.2
|
||||||
The ``StreamHandler`` class now has a ``terminator`` attribute, default
|
The ``StreamHandler`` class now has a ``terminator`` attribute, default
|
||||||
value ``"\n"``, which is used as the terminator when writing a formatted
|
value ``'\n'``, which is used as the terminator when writing a formatted
|
||||||
record to a stream. If you don't want this newline termination, you can
|
record to a stream. If you don't want this newline termination, you can
|
||||||
set the handler instance's ``terminator`` attribute to the empty string.
|
set the handler instance's ``terminator`` attribute to the empty string.
|
||||||
|
|
||||||
|
@ -2604,7 +2609,7 @@ NullHandler
|
||||||
.. versionadded:: 3.1
|
.. versionadded:: 3.1
|
||||||
|
|
||||||
The :class:`NullHandler` class, located in the core :mod:`logging` package,
|
The :class:`NullHandler` class, located in the core :mod:`logging` package,
|
||||||
does not do any formatting or output. It is essentially a "no-op" handler
|
does not do any formatting or output. It is essentially a 'no-op' handler
|
||||||
for use by library developers.
|
for use by library developers.
|
||||||
|
|
||||||
.. class:: NullHandler()
|
.. class:: NullHandler()
|
||||||
|
@ -2690,7 +2695,7 @@ module, supports rotation of disk log files.
|
||||||
the file is closed and a new file is silently opened for output. Rollover occurs
|
the file is closed and a new file is silently opened for output. Rollover occurs
|
||||||
whenever the current log file is nearly *maxBytes* in length; if *maxBytes* is
|
whenever the current log file is nearly *maxBytes* in length; if *maxBytes* is
|
||||||
zero, rollover never occurs. If *backupCount* is non-zero, the system will save
|
zero, rollover never occurs. If *backupCount* is non-zero, the system will save
|
||||||
old log files by appending the extensions ".1", ".2" etc., to the filename. For
|
old log files by appending the extensions '.1', '.2' etc., to the filename. For
|
||||||
example, with a *backupCount* of 5 and a base file name of :file:`app.log`, you
|
example, with a *backupCount* of 5 and a base file name of :file:`app.log`, you
|
||||||
would get :file:`app.log`, :file:`app.log.1`, :file:`app.log.2`, up to
|
would get :file:`app.log`, :file:`app.log.1`, :file:`app.log.2`, up to
|
||||||
:file:`app.log.5`. The file being written to is always :file:`app.log`. When
|
:file:`app.log.5`. The file being written to is always :file:`app.log`. When
|
||||||
|
@ -2887,7 +2892,7 @@ supports sending logging messages to a remote or local Unix syslog.
|
||||||
the form of a ``(host, port)`` tuple. If *address* is not specified,
|
the form of a ``(host, port)`` tuple. If *address* is not specified,
|
||||||
``('localhost', 514)`` is used. The address is used to open a socket. An
|
``('localhost', 514)`` is used. The address is used to open a socket. An
|
||||||
alternative to providing a ``(host, port)`` tuple is providing an address as a
|
alternative to providing a ``(host, port)`` tuple is providing an address as a
|
||||||
string, for example "/dev/log". In this case, a Unix domain socket is used to
|
string, for example '/dev/log'. In this case, a Unix domain socket is used to
|
||||||
send the message to the syslog. If *facility* is not specified,
|
send the message to the syslog. If *facility* is not specified,
|
||||||
:const:`LOG_USER` is used. The type of socket opened depends on the
|
:const:`LOG_USER` is used. The type of socket opened depends on the
|
||||||
*socktype* argument, which defaults to :const:`socket.SOCK_DGRAM` and thus
|
*socktype* argument, which defaults to :const:`socket.SOCK_DGRAM` and thus
|
||||||
|
@ -2897,8 +2902,8 @@ supports sending logging messages to a remote or local Unix syslog.
|
||||||
Note that if your server is not listening on UDP port 514,
|
Note that if your server is not listening on UDP port 514,
|
||||||
:class:`SysLogHandler` may appear not to work. In that case, check what
|
:class:`SysLogHandler` may appear not to work. In that case, check what
|
||||||
address you should be using for a domain socket - it's system dependent.
|
address you should be using for a domain socket - it's system dependent.
|
||||||
For example, on Linux it's usually "/dev/log" but on OS/X it's
|
For example, on Linux it's usually '/dev/log' but on OS/X it's
|
||||||
"/var/run/syslog". You'll need to check your platform and use the
|
'/var/run/syslog'. You'll need to check your platform and use the
|
||||||
appropriate address (you may need to do this check at runtime if your
|
appropriate address (you may need to do this check at runtime if your
|
||||||
application needs to run on several platforms). On Windows, you pretty
|
application needs to run on several platforms). On Windows, you pretty
|
||||||
much have to use the UDP option.
|
much have to use the UDP option.
|
||||||
|
@ -3002,7 +3007,7 @@ supports sending logging messages to a remote or local Unix syslog.
|
||||||
if the default algorithm is not suitable for your needs. The
|
if the default algorithm is not suitable for your needs. The
|
||||||
default algorithm maps ``DEBUG``, ``INFO``, ``WARNING``, ``ERROR`` and
|
default algorithm maps ``DEBUG``, ``INFO``, ``WARNING``, ``ERROR`` and
|
||||||
``CRITICAL`` to the equivalent syslog names, and all other level
|
``CRITICAL`` to the equivalent syslog names, and all other level
|
||||||
names to "warning".
|
names to 'warning'.
|
||||||
|
|
||||||
.. _nt-eventlog-handler:
|
.. _nt-eventlog-handler:
|
||||||
|
|
||||||
|
@ -3326,7 +3331,7 @@ Subclassing QueueHandler
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
You can use a :class:`QueueHandler` subclass to send messages to other kinds
|
You can use a :class:`QueueHandler` subclass to send messages to other kinds
|
||||||
of queues, for example a ZeroMQ "publish" socket. In the example below,the
|
of queues, for example a ZeroMQ 'publish' socket. In the example below,the
|
||||||
socket is created separately and passed to the handler (as its 'queue')::
|
socket is created separately and passed to the handler (as its 'queue')::
|
||||||
|
|
||||||
import zmq # using pyzmq, the Python binding for ZeroMQ
|
import zmq # using pyzmq, the Python binding for ZeroMQ
|
||||||
|
@ -3366,7 +3371,7 @@ Subclassing QueueListener
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
You can also subclass :class:`QueueListener` to get messages from other kinds
|
You can also subclass :class:`QueueListener` to get messages from other kinds
|
||||||
of queues, for example a ZeroMQ "subscribe" socket. Here's an example::
|
of queues, for example a ZeroMQ 'subscribe' socket. Here's an example::
|
||||||
|
|
||||||
class ZeroMQSocketListener(QueueListener):
|
class ZeroMQSocketListener(QueueListener):
|
||||||
def __init__(self, uri, *handlers, **kwargs):
|
def __init__(self, uri, *handlers, **kwargs):
|
||||||
|
@ -3466,8 +3471,8 @@ Filter Objects
|
||||||
``Filters`` can be used by ``Handlers`` and ``Loggers`` for more sophisticated
|
``Filters`` can be used by ``Handlers`` and ``Loggers`` for more sophisticated
|
||||||
filtering than is provided by levels. The base filter class only allows events
|
filtering than is provided by levels. The base filter class only allows events
|
||||||
which are below a certain point in the logger hierarchy. For example, a filter
|
which are below a certain point in the logger hierarchy. For example, a filter
|
||||||
initialized with "A.B" will allow events logged by loggers "A.B", "A.B.C",
|
initialized with 'A.B' will allow events logged by loggers 'A.B', 'A.B.C',
|
||||||
"A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If initialized with the
|
'A.B.C.D', 'A.B.D' etc. but not 'A.BB', 'B.A.B' etc. If initialized with the
|
||||||
empty string, all events are passed.
|
empty string, all events are passed.
|
||||||
|
|
||||||
|
|
||||||
|
@ -3619,7 +3624,7 @@ the options available to you.
|
||||||
+----------------+-------------------------+-----------------------------------------------+
|
+----------------+-------------------------+-----------------------------------------------+
|
||||||
| asctime | ``%(asctime)s`` | Human-readable time when the |
|
| asctime | ``%(asctime)s`` | Human-readable time when the |
|
||||||
| | | :class:`LogRecord` was created. By default |
|
| | | :class:`LogRecord` was created. By default |
|
||||||
| | | this is of the form "2003-07-08 16:49:45,896" |
|
| | | this is of the form '2003-07-08 16:49:45,896' |
|
||||||
| | | (the numbers after the comma are millisecond |
|
| | | (the numbers after the comma are millisecond |
|
||||||
| | | portion of the time). |
|
| | | portion of the time). |
|
||||||
+----------------+-------------------------+-----------------------------------------------+
|
+----------------+-------------------------+-----------------------------------------------+
|
||||||
|
@ -3749,7 +3754,7 @@ with the :mod:`warnings` module.
|
||||||
If *capture* is ``True``, warnings issued by the :mod:`warnings` module will
|
If *capture* is ``True``, warnings issued by the :mod:`warnings` module will
|
||||||
be redirected to the logging system. Specifically, a warning will be
|
be redirected to the logging system. Specifically, a warning will be
|
||||||
formatted using :func:`warnings.formatwarning` and the resulting string
|
formatted using :func:`warnings.formatwarning` and the resulting string
|
||||||
logged to a logger named "py.warnings" with a severity of `WARNING`.
|
logged to a logger named 'py.warnings' with a severity of `WARNING`.
|
||||||
|
|
||||||
If *capture* is ``False``, the redirection of warnings to the logging system
|
If *capture* is ``False``, the redirection of warnings to the logging system
|
||||||
will stop, and warnings will be redirected to their original destinations
|
will stop, and warnings will be redirected to their original destinations
|
||||||
|
@ -3852,8 +3857,8 @@ Configuration dictionary schema
|
||||||
|
|
||||||
Describing a logging configuration requires listing the various
|
Describing a logging configuration requires listing the various
|
||||||
objects to create and the connections between them; for example, you
|
objects to create and the connections between them; for example, you
|
||||||
may create a handler named "console" and then say that the logger
|
may create a handler named 'console' and then say that the logger
|
||||||
named "startup" will send its messages to the "console" handler.
|
named 'startup' will send its messages to the 'console' handler.
|
||||||
These objects aren't limited to those provided by the :mod:`logging`
|
These objects aren't limited to those provided by the :mod:`logging`
|
||||||
module because you might write your own formatter or handler class.
|
module because you might write your own formatter or handler class.
|
||||||
The parameters to these classes may also need to include external
|
The parameters to these classes may also need to include external
|
||||||
|
@ -4316,7 +4321,7 @@ Sections which specify handler configuration are exemplified by the following.
|
||||||
|
|
||||||
The ``class`` entry indicates the handler's class (as determined by :func:`eval`
|
The ``class`` entry indicates the handler's class (as determined by :func:`eval`
|
||||||
in the ``logging`` package's namespace). The ``level`` is interpreted as for
|
in the ``logging`` package's namespace). The ``level`` is interpreted as for
|
||||||
loggers, and ``NOTSET`` is taken to mean "log everything".
|
loggers, and ``NOTSET`` is taken to mean 'log everything'.
|
||||||
|
|
||||||
The ``formatter`` entry indicates the key name of the formatter for this
|
The ``formatter`` entry indicates the key name of the formatter for this
|
||||||
handler. If blank, a default formatter (``logging._defaultFormatter``) is used.
|
handler. If blank, a default formatter (``logging._defaultFormatter``) is used.
|
||||||
|
@ -4387,7 +4392,7 @@ Sections which specify formatter configuration are typified by the following. ::
|
||||||
The ``format`` entry is the overall format string, and the ``datefmt`` entry is
|
The ``format`` entry is the overall format string, and the ``datefmt`` entry is
|
||||||
the :func:`strftime`\ -compatible date/time format string. If empty, the
|
the :func:`strftime`\ -compatible date/time format string. If empty, the
|
||||||
package substitutes ISO8601 format date/times, which is almost equivalent to
|
package substitutes ISO8601 format date/times, which is almost equivalent to
|
||||||
specifying the date format string ``"%Y-%m-%d %H:%M:%S"``. The ISO8601 format
|
specifying the date format string ``'%Y-%m-%d %H:%M:%S'``. The ISO8601 format
|
||||||
also specifies milliseconds, which are appended to the result of using the above
|
also specifies milliseconds, which are appended to the result of using the above
|
||||||
format string, with a comma separator. An example time in ISO8601 format is
|
format string, with a comma separator. An example time in ISO8601 format is
|
||||||
``2003-01-23 00:29:50,411``.
|
``2003-01-23 00:29:50,411``.
|
||||||
|
@ -4409,23 +4414,23 @@ Here is an example of a module using the logging configuration server::
|
||||||
import os
|
import os
|
||||||
|
|
||||||
# read initial config file
|
# read initial config file
|
||||||
logging.config.fileConfig("logging.conf")
|
logging.config.fileConfig('logging.conf')
|
||||||
|
|
||||||
# create and start listener on port 9999
|
# create and start listener on port 9999
|
||||||
t = logging.config.listen(9999)
|
t = logging.config.listen(9999)
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
logger = logging.getLogger("simpleExample")
|
logger = logging.getLogger('simpleExample')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# loop through logging calls to see the difference
|
# loop through logging calls to see the difference
|
||||||
# new configurations make, until Ctrl+C is pressed
|
# new configurations make, until Ctrl+C is pressed
|
||||||
while True:
|
while True:
|
||||||
logger.debug("debug message")
|
logger.debug('debug message')
|
||||||
logger.info("info message")
|
logger.info('info message')
|
||||||
logger.warn("warn message")
|
logger.warn('warn message')
|
||||||
logger.error("error message")
|
logger.error('error message')
|
||||||
logger.critical("critical message")
|
logger.critical('critical message')
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
# cleanup
|
# cleanup
|
||||||
|
@ -4439,18 +4444,18 @@ configuration::
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
import socket, sys, struct
|
import socket, sys, struct
|
||||||
|
|
||||||
data_to_send = open(sys.argv[1], "r").read()
|
data_to_send = open(sys.argv[1], 'r').read()
|
||||||
|
|
||||||
HOST = 'localhost'
|
HOST = 'localhost'
|
||||||
PORT = 9999
|
PORT = 9999
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
print("connecting...")
|
print('connecting...')
|
||||||
s.connect((HOST, PORT))
|
s.connect((HOST, PORT))
|
||||||
print("sending config...")
|
print('sending config...')
|
||||||
s.send(struct.pack(">L", len(data_to_send)))
|
s.send(struct.pack('>L', len(data_to_send)))
|
||||||
s.send(data_to_send)
|
s.send(data_to_send)
|
||||||
s.close()
|
s.close()
|
||||||
print("complete")
|
print('complete')
|
||||||
|
|
||||||
|
|
||||||
More examples
|
More examples
|
||||||
|
@ -4469,30 +4474,30 @@ previous simple module-based configuration example::
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger("simple_example")
|
logger = logging.getLogger('simple_example')
|
||||||
logger.setLevel(logging.DEBUG)
|
logger.setLevel(logging.DEBUG)
|
||||||
# create file handler which logs even debug messages
|
# create file handler which logs even debug messages
|
||||||
fh = logging.FileHandler("spam.log")
|
fh = logging.FileHandler('spam.log')
|
||||||
fh.setLevel(logging.DEBUG)
|
fh.setLevel(logging.DEBUG)
|
||||||
# create console handler with a higher log level
|
# create console handler with a higher log level
|
||||||
ch = logging.StreamHandler()
|
ch = logging.StreamHandler()
|
||||||
ch.setLevel(logging.ERROR)
|
ch.setLevel(logging.ERROR)
|
||||||
# create formatter and add it to the handlers
|
# create formatter and add it to the handlers
|
||||||
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||||
ch.setFormatter(formatter)
|
ch.setFormatter(formatter)
|
||||||
fh.setFormatter(formatter)
|
fh.setFormatter(formatter)
|
||||||
# add the handlers to logger
|
# add the handlers to logger
|
||||||
logger.addHandler(ch)
|
logger.addHandler(ch)
|
||||||
logger.addHandler(fh)
|
logger.addHandler(fh)
|
||||||
|
|
||||||
# "application" code
|
# 'application' code
|
||||||
logger.debug("debug message")
|
logger.debug('debug message')
|
||||||
logger.info("info message")
|
logger.info('info message')
|
||||||
logger.warn("warn message")
|
logger.warn('warn message')
|
||||||
logger.error("error message")
|
logger.error('error message')
|
||||||
logger.critical("critical message")
|
logger.critical('critical message')
|
||||||
|
|
||||||
Notice that the "application" code does not care about multiple handlers. All
|
Notice that the 'application' code does not care about multiple handlers. All
|
||||||
that changed was the addition and configuration of a new handler named *fh*.
|
that changed was the addition and configuration of a new handler named *fh*.
|
||||||
|
|
||||||
The ability to create new handlers with higher- or lower-severity filters can be
|
The ability to create new handlers with higher- or lower-severity filters can be
|
||||||
|
@ -4519,51 +4524,51 @@ the parent. Here is a main module::
|
||||||
import logging
|
import logging
|
||||||
import auxiliary_module
|
import auxiliary_module
|
||||||
|
|
||||||
# create logger with "spam_application"
|
# create logger with 'spam_application'
|
||||||
logger = logging.getLogger("spam_application")
|
logger = logging.getLogger('spam_application')
|
||||||
logger.setLevel(logging.DEBUG)
|
logger.setLevel(logging.DEBUG)
|
||||||
# create file handler which logs even debug messages
|
# create file handler which logs even debug messages
|
||||||
fh = logging.FileHandler("spam.log")
|
fh = logging.FileHandler('spam.log')
|
||||||
fh.setLevel(logging.DEBUG)
|
fh.setLevel(logging.DEBUG)
|
||||||
# create console handler with a higher log level
|
# create console handler with a higher log level
|
||||||
ch = logging.StreamHandler()
|
ch = logging.StreamHandler()
|
||||||
ch.setLevel(logging.ERROR)
|
ch.setLevel(logging.ERROR)
|
||||||
# create formatter and add it to the handlers
|
# create formatter and add it to the handlers
|
||||||
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||||
fh.setFormatter(formatter)
|
fh.setFormatter(formatter)
|
||||||
ch.setFormatter(formatter)
|
ch.setFormatter(formatter)
|
||||||
# add the handlers to the logger
|
# add the handlers to the logger
|
||||||
logger.addHandler(fh)
|
logger.addHandler(fh)
|
||||||
logger.addHandler(ch)
|
logger.addHandler(ch)
|
||||||
|
|
||||||
logger.info("creating an instance of auxiliary_module.Auxiliary")
|
logger.info('creating an instance of auxiliary_module.Auxiliary')
|
||||||
a = auxiliary_module.Auxiliary()
|
a = auxiliary_module.Auxiliary()
|
||||||
logger.info("created an instance of auxiliary_module.Auxiliary")
|
logger.info('created an instance of auxiliary_module.Auxiliary')
|
||||||
logger.info("calling auxiliary_module.Auxiliary.do_something")
|
logger.info('calling auxiliary_module.Auxiliary.do_something')
|
||||||
a.do_something()
|
a.do_something()
|
||||||
logger.info("finished auxiliary_module.Auxiliary.do_something")
|
logger.info('finished auxiliary_module.Auxiliary.do_something')
|
||||||
logger.info("calling auxiliary_module.some_function()")
|
logger.info('calling auxiliary_module.some_function()')
|
||||||
auxiliary_module.some_function()
|
auxiliary_module.some_function()
|
||||||
logger.info("done with auxiliary_module.some_function()")
|
logger.info('done with auxiliary_module.some_function()')
|
||||||
|
|
||||||
Here is the auxiliary module::
|
Here is the auxiliary module::
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
# create logger
|
# create logger
|
||||||
module_logger = logging.getLogger("spam_application.auxiliary")
|
module_logger = logging.getLogger('spam_application.auxiliary')
|
||||||
|
|
||||||
class Auxiliary:
|
class Auxiliary:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.logger = logging.getLogger("spam_application.auxiliary.Auxiliary")
|
self.logger = logging.getLogger('spam_application.auxiliary.Auxiliary')
|
||||||
self.logger.info("creating an instance of Auxiliary")
|
self.logger.info('creating an instance of Auxiliary')
|
||||||
def do_something(self):
|
def do_something(self):
|
||||||
self.logger.info("doing something")
|
self.logger.info('doing something')
|
||||||
a = 1 + 1
|
a = 1 + 1
|
||||||
self.logger.info("done doing something")
|
self.logger.info('done doing something')
|
||||||
|
|
||||||
def some_function():
|
def some_function():
|
||||||
module_logger.info("received a call to \"some_function\"")
|
module_logger.info('received a call to "some_function"')
|
||||||
|
|
||||||
The output looks like this::
|
The output looks like this::
|
||||||
|
|
||||||
|
@ -4584,7 +4589,7 @@ The output looks like this::
|
||||||
2005-03-23 23:47:11,671 - spam_application - INFO -
|
2005-03-23 23:47:11,671 - spam_application - INFO -
|
||||||
calling auxiliary_module.some_function()
|
calling auxiliary_module.some_function()
|
||||||
2005-03-23 23:47:11,672 - spam_application.auxiliary - INFO -
|
2005-03-23 23:47:11,672 - spam_application.auxiliary - INFO -
|
||||||
received a call to "some_function"
|
received a call to 'some_function'
|
||||||
2005-03-23 23:47:11,673 - spam_application - INFO -
|
2005-03-23 23:47:11,673 - spam_application - INFO -
|
||||||
done with auxiliary_module.some_function()
|
done with auxiliary_module.some_function()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue