|
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