|
1 | 1 | ==============================
|
2 |
| -13.12 给内库增加日志功能 |
| 2 | +13.12 给函数库增加日志功能 |
3 | 3 | ==============================
|
4 | 4 |
|
5 | 5 | ----------
|
6 | 6 | 问题
|
7 | 7 | ----------
|
8 |
| -You would like to add a logging capability to a library, but don’t want it to interfere with |
9 |
| -programs that don’t use logging. |
| 8 | +你想给某个函数库增加日志功能,但是又不能影响到那些不使用日志功能的程序。 |
10 | 9 |
|
11 | 10 | |
|
12 | 11 |
|
13 | 12 | ----------
|
14 | 13 | 解决方案
|
15 | 14 | ----------
|
16 |
| -For libraries that want to perform logging, you should create a dedicated logger object, |
17 |
| -and initially configure it as follows: |
| 15 | +对于想要执行日志操作的函数库而已,你应该创建一个专属的 ``logger`` 对象,并且像下面这样初始化配置: |
18 | 16 |
|
19 |
| -# somelib.py |
| 17 | +.. code-block:: python |
20 | 18 |
|
21 |
| -import logging |
22 |
| -log = logging.getLogger(__name__) |
23 |
| -log.addHandler(logging.NullHandler()) |
| 19 | + # somelib.py |
24 | 20 |
|
25 |
| -# Example function (for testing) |
26 |
| -def func(): |
27 |
| - log.critical('A Critical Error!') |
28 |
| - log.debug('A debug message') |
| 21 | + import logging |
| 22 | + log = logging.getLogger(__name__) |
| 23 | + log.addHandler(logging.NullHandler()) |
29 | 24 |
|
30 |
| -With this configuration, no logging will occur by default. For example: |
| 25 | + # Example function (for testing) |
| 26 | + def func(): |
| 27 | + log.critical('A Critical Error!') |
| 28 | + log.debug('A debug message') |
31 | 29 |
|
32 |
| ->>> import somelib |
33 |
| ->>> somelib.func() |
34 |
| ->>> |
| 30 | +使用这个配置,默认情况下不会打印日志。例如: |
35 | 31 |
|
36 |
| -However, if the logging system gets configured, log messages will start to appear. For |
37 |
| -example: |
| 32 | +.. code-block:: python |
38 | 33 |
|
39 |
| ->>> import logging |
40 |
| ->>> logging.basicConfig() |
41 |
| ->>> somelib.func() |
42 |
| -CRITICAL:somelib:A Critical Error! |
43 |
| ->>> |
| 34 | + >>> import somelib |
| 35 | + >>> somelib.func() |
| 36 | + >>> |
| 37 | +
|
| 38 | +不过,如果配置过日志系统,那么日志消息打印就开始生效,例如: |
| 39 | + |
| 40 | +:: |
| 41 | + |
| 42 | + >>> import logging |
| 43 | + >>> logging.basicConfig() |
| 44 | + >>> somelib.func() |
| 45 | + CRITICAL:somelib:A Critical Error! |
| 46 | + >>> |
44 | 47 |
|
45 | 48 | |
|
46 | 49 |
|
47 | 50 | ----------
|
48 | 51 | 讨论
|
49 | 52 | ----------
|
50 |
| -Libraries present a special problem for logging, since information about the environ‐ |
51 |
| -ment in which they are used isn’t known. As a general rule, you should never write |
52 |
| -library code that tries to configure the logging system on its own or which makes as‐ |
53 |
| -sumptions about an already existing logging configuration. Thus, you need to take great |
54 |
| -care to provide isolation. |
55 |
| -The call to getLogger(__name__) creates a logger module that has the same name as |
56 |
| -the calling module. Since all modules are unique, this creates a dedicated logger that is |
57 |
| -likely to be separate from other loggers. |
58 |
| - |
59 |
| -The log.addHandler(logging.NullHandler()) operation attaches a null handler to |
60 |
| -the just created logger object. A null handler ignores all logging messages by default. |
61 |
| -Thus, if the library is used and logging is never configured, no messages or warnings |
62 |
| -will appear. |
63 |
| -One subtle feature of this recipe is that the logging of individual libraries can be inde‐ |
64 |
| -pendently configured, regardless of other logging settings. For example, consider the |
65 |
| -following code: |
66 |
| - |
67 |
| ->>> import logging |
68 |
| ->>> logging.basicConfig(level=logging.ERROR) |
69 |
| ->>> import somelib |
70 |
| ->>> somelib.func() |
71 |
| -CRITICAL:somelib:A Critical Error! |
72 |
| - |
73 |
| ->>> # Change the logging level for 'somelib' only |
74 |
| ->>> logging.getLogger('somelib').level=logging.DEBUG |
75 |
| ->>> somelib.func() |
76 |
| -CRITICAL:somelib:A Critical Error! |
77 |
| -DEBUG:somelib:A debug message |
78 |
| ->>> |
79 |
| - |
80 |
| -Here, the root logger has been configured to only output messages at the ERROR level or |
81 |
| -higher. However, the level of the logger for somelib has been separately configured to |
82 |
| -output debugging messages. That setting takes precedence over the global setting. |
83 |
| -The ability to change the logging settings for a single module like this can be a useful |
84 |
| -debugging tool, since you don’t have to change any of the global logging settings—simply |
85 |
| -change the level for the one module where you want more output. |
86 |
| -The “Logging HOWTO” has more information about configuring the logging module |
87 |
| -and other useful tips. |
| 53 | +通常来讲,你不应该在函数库代码中自己配置日志系统,或者是已经假定有个已经存在的日志配置了。 |
| 54 | + |
| 55 | +调用 ``getLogger(__name__)`` 创建一个和调用模块同名的logger模块。 |
| 56 | +由于模块都是唯一的,因此创建的logger也将是唯一的。 |
| 57 | + |
| 58 | +``log.addHandler(logging.NullHandler())`` 操作将一个空处理器绑定到刚刚已经创建好的logger对象上。 |
| 59 | +一个空处理器默认会忽略调用所有的日志消息。 |
| 60 | +因此,如果使用该函数库的时候还没有配置日志,那么将不会有消息或警告出现。 |
| 61 | + |
| 62 | +还有一点就是对于各个函数库的日志配置可以是相互独立的,不影响其他库的日志配置。 |
| 63 | +例如,对于如下的代码: |
| 64 | + |
| 65 | +.. code-block:: python |
| 66 | +
|
| 67 | + >>> import logging |
| 68 | + >>> logging.basicConfig(level=logging.ERROR) |
| 69 | +
|
| 70 | + >>> import somelib |
| 71 | + >>> somelib.func() |
| 72 | + CRITICAL:somelib:A Critical Error! |
| 73 | +
|
| 74 | + >>> # Change the logging level for 'somelib' only |
| 75 | + >>> logging.getLogger('somelib').level=logging.DEBUG |
| 76 | + >>> somelib.func() |
| 77 | + CRITICAL:somelib:A Critical Error! |
| 78 | + DEBUG:somelib:A debug message |
| 79 | + >>> |
| 80 | +
|
| 81 | +在这里,根日志被配置成仅仅输出ERROR或更高级别的消息。 |
| 82 | +不过 ,``somelib`` 的日志级别被单独配置成可以输出debug级别的消息,它的优先级比全局配置高。 |
| 83 | +像这样更改单独模块的日志配置对于调试来讲是很方便的, |
| 84 | +因为你无需去更改任何的全局日志配置——只需要修改你想要更多输出的模块的日志等级。 |
| 85 | + |
| 86 | +`Logging HOWTO <https://docs.python.org/3/howto/logging.html>`_ |
| 87 | +详细介绍了如何配置日志模块和其他有用技巧,可以参阅下。 |
0 commit comments