mirror of
https://github.com/fofolee/uTools-Manuals.git
synced 2025-06-08 23:14:06 +08:00
148 lines
74 KiB
HTML
148 lines
74 KiB
HTML
<div class="body" role="main"><div class="section" id="module-logging.config"><h1><span class="yiyi-st" id="yiyi-10">16.7. <a class="reference internal" href="#module-logging.config" title="logging.config: Configuration of the logging module."><code class="xref py py-mod docutils literal"><span class="pre">logging.config</span></code></a> - 记录配置</span></h1><p><span class="yiyi-st" id="yiyi-11"><strong>源代码:</strong> <a class="reference external" href="https://hg.python.org/cpython/file/3.5/Lib/logging/config.py">Lib / logging / config.py</a></span></p><div class="sidebar"><p class="first sidebar-title"><span class="yiyi-st" id="yiyi-12">重要</span></p><p><span class="yiyi-st" id="yiyi-13">该页只包含参考信息。</span><span class="yiyi-st" id="yiyi-14">关于教程请参见</span></p><ul class="last simple"><li><span class="yiyi-st" id="yiyi-15"><a class="reference internal" href="../howto/logging.html#logging-basic-tutorial"><span>Basic Tutorial</span></a></span></li><li><span class="yiyi-st" id="yiyi-16"><a class="reference internal" href="../howto/logging.html#logging-advanced-tutorial"><span>Advanced Tutorial</span></a></span></li><li><span class="yiyi-st" id="yiyi-17"><a class="reference internal" href="../howto/logging-cookbook.html#logging-cookbook"><span>Logging Cookbook</span></a></span></li></ul></div><p><span class="yiyi-st" id="yiyi-18">该章描述用于配置日志模块的API。</span></p><div class="section" id="configuration-functions"><h2><span class="yiyi-st" id="yiyi-19">16.7.1. </span><span class="yiyi-st" id="yiyi-20">Configuration functions</span></h2><p><span class="yiyi-st" id="yiyi-21">下列函数配置日志模块。</span><span class="yiyi-st" id="yiyi-22">它们都在<a class="reference internal" href="#module-logging.config" title="logging.config: Configuration of the logging module."><code class="xref py py-mod docutils literal"><span class="pre">logging.config</span></code></a>模块中。</span><span class="yiyi-st" id="yiyi-23">这些使用是可选的—你可以使用这些函数配置日志模块或者通过调用定义在<a class="reference internal" href="logging.html#module-logging" title="logging: Flexible event logging system for applications."><code class="xref py py-mod docutils literal"><span class="pre">logging</span></code></a>模块中的主要API来配置,或者通过定义<a class="reference internal" href="logging.html#module-logging" title="logging: Flexible event logging system for applications."><code class="xref py py-mod docutils literal"><span class="pre">logging</span></code></a> 和<a class="reference internal" href="logging.handlers.html#module-logging.handlers" title="logging.handlers: Handlers for the logging module."><code class="xref py py-mod docutils literal"><span class="pre">logging.handlers</span></code></a>中的handlers来配置日志模块。</span></p><dl class="function"><dt id="logging.config.dictConfig"><span class="yiyi-st" id="yiyi-24"> <code class="descclassname">logging.config.</code><code class="descname">dictConfig</code><span class="sig-paren">(</span><em>config</em><span class="sig-paren">)</span></span></dt><dd><span class="yiyi-st" id="yiyi-26"><blockquote> <div><p>Takes the logging configuration from a dictionary. The contents of this dictionary are described in <a class="reference internal" href="#logging-config-dictschema"><span>Configuration dictionary schema</span></a> below.</p> <p>If an error is encountered during configuration, this function will raise a <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal"><span class="pre">ValueError</span></code></a>, <a class="reference internal" href="exceptions.html#TypeError" title="TypeError"><code class="xref py py-exc docutils literal"><span class="pre">TypeError</span></code></a>, <a class="reference internal" href="exceptions.html#AttributeError" title="AttributeError"><code class="xref py py-exc docutils literal"><span class="pre">AttributeError</span></code></a> or <a class="reference internal" href="exceptions.html#ImportError" title="ImportError"><code class="xref py py-exc docutils literal"><span class="pre">ImportError</span></code></a> with a suitably descriptive message. The following is a (possibly incomplete) list of conditions which will raise an error:</p> <ul class="simple"> <li>A <code class="docutils literal"><span class="pre">level</span></code> which is not a string or which is a string not corresponding to an actual logging level.</li> <li>A <code class="docutils literal"><span class="pre">propagate</span></code> value which is not a boolean.</li> <li>An id which does not have a corresponding destination.</li> <li>A non-existent handler id found during an incremental call.</li> <li>An invalid logger name.</li> <li>Inability to resolve to an internal or external object.</li> </ul> <p>Parsing is performed by the <code class="xref py py-class docutils literal"><span class="pre">DictConfigurator</span></code> class, whose constructor is passed the dictionary used for configuration, and has a <code class="xref py py-meth docutils literal"><span class="pre">configure()</span></code> method. The <a class="reference internal" href="#module-logging.config" title="logging.config: Configuration of the logging module."><code class="xref py py-mod docutils literal"><span class="pre">logging.config</span></code></a> module has a callable attribute <code class="xref py py-attr docutils literal"><span class="pre">dictConfigClass</span></code> which is initially set to <code class="xref py py-class docutils literal"><span class="pre">DictConfigurator</span></code>. You can replace the value of <code class="xref py py-attr docutils literal"><span class="pre">dictConfigClass</span></code> with a suitable implementation of your own.</p> <p><a class="reference internal" href="#logging.config.dictConfig" title="logging.config.dictConfig"><code class="xref py py-func docutils literal"><span class="pre">dictConfig()</span></code></a> calls <code class="xref py py-attr docutils literal"><span class="pre">dictConfigClass</span></code> passing the specified dictionary, and then calls the <code class="xref py py-meth docutils literal"><span class="pre">configure()</span></code> method on the returned object to put the configuration into effect:</p> <pre><code class="language-python"><span></span><span class="k">def</span> <span class="nf">dictConfig</span><span class="p">(</span><span class="n">config</span><span class="p">):</span> <span class="n">dictConfigClass</span><span class="p">(</span><span class="n">config</span><span class="p">)</span><span class="o">.</span><span class="n">configure</span><span class="p">()</span> </code></pre> <p>For example, a subclass of <code class="xref py py-class docutils literal"><span class="pre">DictConfigurator</span></code> could call <code class="docutils literal"><span class="pre">DictConfigurator.__init__()</span></code> in its own <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal"><span class="pre">__init__()</span></code></a>, then set up custom prefixes which would be usable in the subsequent <code class="xref py py-meth docutils literal"><span class="pre">configure()</span></code> call. <code class="xref py py-attr docutils literal"><span class="pre">dictConfigClass</span></code> would be bound to this new subclass, and then <a class="reference internal" href="#logging.config.dictConfig" title="logging.config.dictConfig"><code class="xref py py-func docutils literal"><span class="pre">dictConfig()</span></code></a> could be called exactly as in the default, uncustomized state.</p> </div></blockquote></span><div class="versionadded"><p><span class="yiyi-st" id="yiyi-25"><span class="versionmodified">版本3.2中的新功能。</span></span></p></div></dd></dl><dl class="function"><dt id="logging.config.fileConfig"><span class="yiyi-st" id="yiyi-27"> <code class="descclassname">logging.config.</code><code class="descname">fileConfig</code><span class="sig-paren">(</span><em>fname</em>, <em>defaults=None</em>, <em>disable_existing_loggers=True</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-28">从<a class="reference internal" href="configparser.html#module-configparser" title="configparser: Configuration file parser."><code class="xref py py-mod docutils literal"><span class="pre">configparser</span></code></a> -format文件读取日志记录配置。</span><span class="yiyi-st" id="yiyi-29">文件格式描述于<a class="reference internal" href="#logging-config-fileformat"><span>Configuration file format</span></a>。</span><span class="yiyi-st" id="yiyi-30">该函数可以从应用中多次调用,允许最终用户可以从各种预先配置好的配置中选择(如果开发者提供了展示配置并装载选择的配置的机制的话)。</span></p><table class="docutils field-list" frame="void" rules="none"><tbody valign="top"><tr class="field-odd field"><th class="field-name"><span class="yiyi-st" id="yiyi-31">参数:</span></th><td class="field-body"><ul class="first last simple"><li><span class="yiyi-st" id="yiyi-32"><strong>fname</strong> - 文件名或类文件对象,或从<a class="reference internal" href="configparser.html#configparser.RawConfigParser" title="configparser.RawConfigParser"><code class="xref py py-class docutils literal"><span class="pre">RawConfigParser</span></code></a>派生的实例。</span><span class="yiyi-st" id="yiyi-33">If a <code class="docutils literal"><span class="pre">RawConfigParser</span></code>-derived instance is passed, it is used as is. </span><span class="yiyi-st" id="yiyi-34">否则,将实例化<code class="xref py py-class docutils literal"><span class="pre">Configparser</span></code>,并且从<code class="docutils literal"><span class="pre">fname</span></code>中传递的对象读取配置。</span><span class="yiyi-st" id="yiyi-35">如果有一个<a class="reference internal" href="readline.html#module-readline" title="readline: GNU readline support for Python. (Unix)"><code class="xref py py-meth docutils literal"><span class="pre">readline()</span></code></a>方法,则假定它是一个类文件对象,并使用<a class="reference internal" href="configparser.html#configparser.ConfigParser.read_file" title="configparser.ConfigParser.read_file"><code class="xref py py-meth docutils literal"><span class="pre">read_file()</span></code></a>读取;否则,假定它是一个文件名,并传递给<a class="reference internal" href="configparser.html#configparser.ConfigParser.read" title="configparser.ConfigParser.read"><code class="xref py py-meth docutils literal"><span class="pre">read()</span></code></a>。</span></li><li><span class="yiyi-st" id="yiyi-36"><strong>defaults</strong> – 该参数指明了传给ConfigParser的默认值。</span></li><li><span class="yiyi-st" id="yiyi-37"><strong>disable_existing_loggers</strong> - 如果指定为<code class="docutils literal"><span class="pre">False</span></code>,则在进行此调用时存在的记录器将保持启用状态。</span><span class="yiyi-st" id="yiyi-38">默认值为<code class="docutils literal"><span class="pre">True</span></code>以保证老的行为向前兼容。</span><span class="yiyi-st" id="yiyi-39">该行为禁用已存的logger,除非它们或者它们的祖先明确的出现在日志配置中。</span></li></ul></td></tr></tbody></table><div class="versionchanged"><p><span class="yiyi-st" id="yiyi-40"><span class="versionmodified">在版本3.4中更改:</span> <a class="reference internal" href="configparser.html#configparser.RawConfigParser" title="configparser.RawConfigParser"><code class="xref py py-class docutils literal"><span class="pre">RawConfigParser</span></code></a>的子类的实例现在被接受为<code class="docutils literal"><span class="pre">fname</span></code>的值。</span><span class="yiyi-st" id="yiyi-41">这有助于:</span></p><ul class="simple"><li><span class="yiyi-st" id="yiyi-42">使用配置文件,其中日志配置只是整个应用程序配置的一部分。</span></li><li><span class="yiyi-st" id="yiyi-43">使用从文件读取的配置,然后由使用应用程序修改(例如,</span><span class="yiyi-st" id="yiyi-44">基于命令行参数或运行时环境的其他方面),然后传递给<code class="docutils literal"><span class="pre">fileConfig</span></code>。</span></li></ul></div></dd></dl><dl class="function"><dt id="logging.config.listen"><span class="yiyi-st" id="yiyi-45"> <code class="descclassname">logging.config.</code><code class="descname">listen</code><span class="sig-paren">(</span><em>port=DEFAULT_LOGGING_CONFIG_PORT</em>, <em>verify=None</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-46">在指定的端口起一个socket服务器,以监听新的配置。</span><span class="yiyi-st" id="yiyi-47">如果没有指定端口,使用模块默认的<code class="xref py py-const docutils literal"><span class="pre">DEFAULT_LOGGING_CONFIG_PORT</span></code>。</span><span class="yiyi-st" id="yiyi-48">日志配置以文件形式发送,可以用<a class="reference internal" href="#logging.config.fileConfig" title="logging.config.fileConfig"><code class="xref py py-func docutils literal"><span class="pre">fileConfig()</span></code></a>处理。</span><span class="yiyi-st" id="yiyi-49">返回<a class="reference internal" href="threading.html#threading.Thread" title="threading.Thread"><code class="xref py py-class docutils literal"><span class="pre">Thread</span></code></a>实例,可以在该线程上调用<a class="reference internal" href="threading.html#threading.Thread.start" title="threading.Thread.start"><code class="xref py py-meth docutils literal"><span class="pre">start()</span></code></a>来启动服务器,可以在合适的时候<a class="reference internal" href="threading.html#threading.Thread.join" title="threading.Thread.join"><code class="xref py py-meth docutils literal"><span class="pre">join()</span></code></a>该线程。</span><span class="yiyi-st" id="yiyi-50">调用<a class="reference internal" href="#logging.config.stopListening" title="logging.config.stopListening"><code class="xref py py-func docutils literal"><span class="pre">stopListening()</span></code></a>以停止服务器。</span></p><p><span class="yiyi-st" id="yiyi-51">如果指定,<code class="docutils literal"><span class="pre">verify</span></code>参数应该是一个可调用,它应该验证在套接字上接收的字节是否有效并且应该被处理。</span><span class="yiyi-st" id="yiyi-52">这可以通过对通过套接字发送的内容进行加密和/或签名,使得<code class="docutils literal"><span class="pre">verify</span></code>可调用可以执行声明验证和/或解密来完成。</span><span class="yiyi-st" id="yiyi-53">使用单个参数调用<code class="docutils literal"><span class="pre">verify</span></code> callable - 跨套接字接收的字节,并应返回要处理的字节,或None,以指示应丢弃字节。</span><span class="yiyi-st" id="yiyi-54">返回的字节可以与以字节传递的字节相同(例如,</span><span class="yiyi-st" id="yiyi-55">当只进行验证时),或者它们可以完全不同(可能是如果执行解密)。</span></p><p><span class="yiyi-st" id="yiyi-56">要向socket发送配置,从配置文件中读入配置,将其以字节流的方式发送至socket,最开始为4字节长的字节流的二进制长度,即<code class="docutils literal"><span class="pre">struct.pack('>L',</span> <span class="pre">n)</span></code>。</span></p><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-57">注意</span></p><p class="last"><span class="yiyi-st" id="yiyi-58">因为部分配置会传给<a class="reference internal" href="functions.html#eval" title="eval"><code class="xref py py-func docutils literal"><span class="pre">eval()</span></code></a>,使用该函数可能有安全风险。</span><span class="yiyi-st" id="yiyi-59">当该函数只绑定于<code class="docutils literal"><span class="pre">localhost</span></code>的socket,也不接受远端机器的连接,调用<a class="reference internal" href="#logging.config.listen" title="logging.config.listen"><code class="xref py py-func docutils literal"><span class="pre">listen()</span></code></a>的进程的帐号就有可能运行不受信任的代码。</span><span class="yiyi-st" id="yiyi-60">特别的,如果调用<a class="reference internal" href="#logging.config.listen" title="logging.config.listen"><code class="xref py py-func docutils literal"><span class="pre">listen()</span></code></a>的进程运行于多用户机器,而这些用户彼此并不信任,那么一个恶意用户可以在受害用户的进程中运行本质上来说任意的代码,只需要连接到受害用户的<a class="reference internal" href="#logging.config.listen" title="logging.config.listen"><code class="xref py py-func docutils literal"><span class="pre">listen()</span></code></a> socket,然后发送配置,其实是攻击者想要在受害者进程中执行的任何代码。</span><span class="yiyi-st" id="yiyi-61">如果使用默认端口这尤为容易,就算是用了不同的端口也不算太难。</span><span class="yiyi-st" id="yiyi-62">为避免发生这种情况,请使用<a class="reference internal" href="#logging.config.listen" title="logging.config.listen"><code class="xref py py-func docutils literal"><span class="pre">listen()</span></code></a>的<code class="docutils literal"><span class="pre">verify</span></code>参数防止应用无法识别的配置。</span></p></div><div class="versionchanged"><p><span class="yiyi-st" id="yiyi-63"><span class="versionmodified">在版本3.4中更改:</span>添加了<code class="docutils literal"><span class="pre">verify</span></code>参数。</span></p></div></dd></dl><dl class="function"><dt id="logging.config.stopListening"><span class="yiyi-st" id="yiyi-64"> <code class="descclassname">logging.config.</code><code class="descname">stopListening</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-65">停止<a class="reference internal" href="#logging.config.listen" title="logging.config.listen"><code class="xref py py-func docutils literal"><span class="pre">listen()</span></code></a>返回的服务器的监听。</span><span class="yiyi-st" id="yiyi-66">典型的在<a class="reference internal" href="#logging.config.listen" title="logging.config.listen"><code class="xref py py-func docutils literal"><span class="pre">listen()</span></code></a>的返回值上调用<code class="xref py py-meth docutils literal"><span class="pre">join()</span></code>之前调用该函数。</span></p></dd></dl></div><div class="section" id="configuration-dictionary-schema"><h2><span class="yiyi-st" id="yiyi-67">16.7.2. </span><span class="yiyi-st" id="yiyi-68">Configuration dictionary schema</span></h2><p><span class="yiyi-st" id="yiyi-69">描述日志记录配置需要列出要创建的各种对象以及它们之间的连接;例如,您可以创建一个名为“console”的处理程序,然后说,名为“startup”的记录器将其消息发送到“控制台”处理程序。</span><span class="yiyi-st" id="yiyi-70">并不限于<a class="reference internal" href="logging.html#module-logging" title="logging: Flexible event logging system for applications."><code class="xref py py-mod docutils literal"><span class="pre">logging</span></code></a>模块所提供的对象,因为你可以写自己的formatter或者handler类。 </span><span class="yiyi-st" id="yiyi-71">这些类的参数也许需要包含<code class="docutils literal"><span class="pre">sys.stderr</span></code>这样的外部对象。</span><span class="yiyi-st" id="yiyi-72">描述对象将其连接的语法定义于下面的<a class="reference internal" href="#logging-config-dict-connections"><span>Object connections</span></a>。</span></p><div class="section" id="dictionary-schema-details"><h3><span class="yiyi-st" id="yiyi-73">16.7.2.1. </span><span class="yiyi-st" id="yiyi-74">Dictionary Schema Details</span></h3><p><span class="yiyi-st" id="yiyi-75">传递给<a class="reference internal" href="#logging.config.dictConfig" title="logging.config.dictConfig"><code class="xref py py-func docutils literal"><span class="pre">dictConfig()</span></code></a>的字典必需包含下列键值:</span></p><ul class="simple"><li><span class="yiyi-st" id="yiyi-76"><em>version</em> - 表示模式版本的整数值。</span><span class="yiyi-st" id="yiyi-77">目前唯一的有效值为1,但是有这个键允许模式演化,同时保留了向前兼容性。</span></li></ul><p><span class="yiyi-st" id="yiyi-78">所有其它键都是可选的,但是如果存在,如下述解读。</span><span class="yiyi-st" id="yiyi-79">在下面如果提到了‘配置字典’,特殊键<code class="docutils literal"><span class="pre">'()'</span></code>将会被检查,以确定是否需要自定义的初始化。</span><span class="yiyi-st" id="yiyi-80">如果是,则使用以下<a class="reference internal" href="#logging-config-dict-userdef"><span>User-defined objects</span></a>中描述的机制创建实例;否则,上下文用于确定要实例化的内容。</span></p><ul><li><p class="first"><span class="yiyi-st" id="yiyi-81"><em>formatters</em> - 对应的值是个字典,其每一个键都是formatter标识符,每一个值又是个字典,描述了如何配置对应的 <a class="reference internal" href="logging.html#logging.Formatter" title="logging.Formatter"><code class="xref py py-class docutils literal"><span class="pre">Formatter</span></code></a> 实例。</span></p><p><span class="yiyi-st" id="yiyi-82">搜寻配置字典中的<code class="docutils literal"><span class="pre">format</span></code> 和 <code class="docutils literal"><span class="pre">datefmt</span></code>键,(默认为<code class="docutils literal"><span class="pre">None</span></code>),以构造<a class="reference internal" href="logging.html#logging.Formatter" title="logging.Formatter"><code class="xref py py-class docutils literal"><span class="pre">Formatter</span></code></a>实例。</span></p></li><li><p class="first"><span class="yiyi-st" id="yiyi-83"><em>filters</em> - 对应的值是个字典,其每一个键都是filter标识符,每一个值又是个字典,描述了如何配置对应的 Filter 实例。</span></p><p><span class="yiyi-st" id="yiyi-84">对配置的dict搜索密钥<code class="docutils literal"><span class="pre">name</span></code>(默认为空字符串),这用于构造一个<a class="reference internal" href="logging.html#logging.Filter" title="logging.Filter"><code class="xref py py-class docutils literal"><span class="pre">logging.Filter</span></code></a>实例。</span></p></li><li><p class="first"><span class="yiyi-st" id="yiyi-85"><em>handlers</em> - 对应的值是个字典,其每一个键都是handler标识符,每一个值又是个字典,描述了如何配置对应的Handler实例。</span></p><p><span class="yiyi-st" id="yiyi-86">搜寻配置字典中的下述键:</span></p><ul class="simple"><li><span class="yiyi-st" id="yiyi-87"><code class="docutils literal"><span class="pre">class</span></code>(强制性)。</span><span class="yiyi-st" id="yiyi-88">handler类的完全限定名。</span></li><li><span class="yiyi-st" id="yiyi-89"><code class="docutils literal"><span class="pre">level</span></code>(可选)。</span><span class="yiyi-st" id="yiyi-90">handler的级别。</span></li><li><span class="yiyi-st" id="yiyi-91"><code class="docutils literal"><span class="pre">formatter</span></code>(可选)。</span><span class="yiyi-st" id="yiyi-92">该handler的formatter的标识符。</span></li><li><span class="yiyi-st" id="yiyi-93"><code class="docutils literal"><span class="pre">filters</span></code>(可选)。</span><span class="yiyi-st" id="yiyi-94">该handler的filter的标识符的列表。</span></li></ul><p><span class="yiyi-st" id="yiyi-95">所有<em>其它</em>键被当作关键字参数传给handler的构造函数。</span><span class="yiyi-st" id="yiyi-96">例如,给定如下代码片段:</span></p><div class="highlight-yaml"><div class="highlight"><pre><span></span><span class="l l-Scalar l-Scalar-Plain">handlers</span><span class="p p-Indicator">:</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">console</span><span class="p p-Indicator">:</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">class</span> <span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">logging.StreamHandler</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">formatter</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">brief</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">level</span> <span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">INFO</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">filters</span><span class="p p-Indicator">:</span> <span class="p p-Indicator">[</span><span class="nv">allow_foo</span><span class="p p-Indicator">]</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">stream</span> <span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">ext://sys.stdout</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">file</span><span class="p p-Indicator">:</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">class</span> <span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">logging.handlers.RotatingFileHandler</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">formatter</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">precise</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">filename</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">logconfig.log</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">maxBytes</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">1024</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">backupCount</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">3</span>
|
||
</pre></div></div><p><span class="yiyi-st" id="yiyi-97">具有标识<code class="docutils literal"><span class="pre">console</span></code>的处理程序将使用<code class="docutils literal"><span class="pre">sys.stdout</span></code>作为基础流实例化为<a class="reference internal" href="logging.handlers.html#logging.StreamHandler" title="logging.StreamHandler"><code class="xref py py-class docutils literal"><span class="pre">logging.StreamHandler</span></code></a>。</span><span class="yiyi-st" id="yiyi-98">标识符为<code class="docutils literal"><span class="pre">file</span></code>的handler初始化为<a class="reference internal" href="logging.handlers.html#logging.handlers.RotatingFileHandler" title="logging.handlers.RotatingFileHandler"><code class="xref py py-class docutils literal"><span class="pre">logging.handlers.RotatingFileHandler</span></code></a>,<code class="docutils literal"><span class="pre">filename='logconfig.log',</span> <span class="pre">maxBytes=1024,</span> <span class="pre">backupCount=3</span></code>为其构造函数的参数。</span></p></li><li><p class="first"><span class="yiyi-st" id="yiyi-99"><em>loggers</em> - 对应的值是个字典,其每一个键都是logger的名字,每一个值又是个字典,描述了如何配置对应的Logger实例。</span></p><p><span class="yiyi-st" id="yiyi-100">搜寻配置字典中的下述键:</span></p><ul class="simple"><li><span class="yiyi-st" id="yiyi-101"><code class="docutils literal"><span class="pre">level</span></code>(可选)。</span><span class="yiyi-st" id="yiyi-102">logger的级别。</span></li><li><span class="yiyi-st" id="yiyi-103"><code class="docutils literal"><span class="pre">propagate</span></code>(可选)。</span><span class="yiyi-st" id="yiyi-104">logger的传播设置。</span></li><li><span class="yiyi-st" id="yiyi-105"><code class="docutils literal"><span class="pre">filters</span></code>(可选)。</span><span class="yiyi-st" id="yiyi-106">logger的filter的标识符的列表。</span></li><li><span class="yiyi-st" id="yiyi-107"><code class="docutils literal"><span class="pre">handlers</span></code>(可选)。</span><span class="yiyi-st" id="yiyi-108">logger的handler的标识符的列表。</span></li></ul><p><span class="yiyi-st" id="yiyi-109">指定的logger通过级别、传播、filter和handler来配置。</span></p></li><li><p class="first"><span class="yiyi-st" id="yiyi-110"><em>root</em> - 根logger的配置。</span><span class="yiyi-st" id="yiyi-111">配置处理和其它logger一样,<code class="docutils literal"><span class="pre">propagate</span></code>设定不可用。</span></p></li><li><p class="first"><span class="yiyi-st" id="yiyi-112"><em>incremental</em> - 配置是否是当前配置的增量配置。</span><span class="yiyi-st" id="yiyi-113">默认值为<code class="docutils literal"><span class="pre">False</span></code>,意味着指定的配置取代已存的配置,就和<a class="reference internal" href="#logging.config.fileConfig" title="logging.config.fileConfig"><code class="xref py py-func docutils literal"><span class="pre">fileConfig()</span></code></a>API的语义一样。</span></p><p><span class="yiyi-st" id="yiyi-114">如果为<code class="docutils literal"><span class="pre">True</span></code>,配置的处理描述于<a class="reference internal" href="#logging-config-dict-incremental"><span>Incremental Configuration</span></a>章节。</span></p></li><li><p class="first"><span class="yiyi-st" id="yiyi-115"><em>disable_existing_loggers</em> - 是否禁用已存的logger。</span><span class="yiyi-st" id="yiyi-116">该设定模仿了<a class="reference internal" href="#logging.config.fileConfig" title="logging.config.fileConfig"><code class="xref py py-func docutils literal"><span class="pre">fileConfig()</span></code></a>同名参数的行为。</span><span class="yiyi-st" id="yiyi-117">如果缺少该参数,默认为<code class="docutils literal"><span class="pre">True</span></code>。</span><span class="yiyi-st" id="yiyi-118">如果<em>incremental</em>为<code class="docutils literal"><span class="pre">True</span></code>,该值被忽略。</span></p></li></ul></div><div class="section" id="incremental-configuration"><h3><span class="yiyi-st" id="yiyi-119">16.7.2.2. </span><span class="yiyi-st" id="yiyi-120">Incremental Configuration</span></h3><p><span class="yiyi-st" id="yiyi-121">很难为增量配置提供完整的弹性。</span><span class="yiyi-st" id="yiyi-122">例如,因为filter和formatter这样的对象是匿名的,一旦建立了配置,就很难在配置的时候去引用这些匿名对象。</span></p><p><span class="yiyi-st" id="yiyi-123">此外,一旦配置被建立,在运行时任意地改变记录器,处理器,过滤器,格式化器的对象图就不是有说服力的情况;可以通过设置级别(以及在记录器的情况下,传播标志)来控制记录器和处理器的冗长性。</span><span class="yiyi-st" id="yiyi-124">以安全的方式任意地改变对象图在多线程环境中是有问题的;虽然不是不可能,但是它的好处并不值得它为实现增加的复杂性。</span></p><p><span class="yiyi-st" id="yiyi-125">因此,当配置中<code class="docutils literal"><span class="pre">incremental</span></code>键值存在且为<code class="docutils literal"><span class="pre">True</span></code>,系统会完全的忽略任何的<code class="docutils literal"><span class="pre">formatters</span></code>和<code class="docutils literal"><span class="pre">filters</span></code>条目,只处理<code class="docutils literal"><span class="pre">level</span></code>条目中的<code class="docutils literal"><span class="pre">handlers</span></code>设置,以及<code class="docutils literal"><span class="pre">level</span></code>和<code class="docutils literal"><span class="pre">propagate</span></code>条目中的<code class="docutils literal"><span class="pre">loggers</span></code>和<code class="docutils literal"><span class="pre">root</span></code>设置。</span></p><p><span class="yiyi-st" id="yiyi-126">配置可以以序列化的字典通过网络发往套接字监听器。</span><span class="yiyi-st" id="yiyi-127">因此,长时间运行的应用的日志冗余度可以随时间修改而不需要重启应用。</span></p></div><div class="section" id="object-connections"><h3><span class="yiyi-st" id="yiyi-128">16.7.2.3. </span><span class="yiyi-st" id="yiyi-129">Object connections</span></h3><p><span class="yiyi-st" id="yiyi-130">模式描述了一组日志对象 - logger、handler、formatter、filter - 它们在一个对象图中彼此连接。</span><span class="yiyi-st" id="yiyi-131">因此模式需要表示对象间的连接。</span><span class="yiyi-st" id="yiyi-132">例如,一旦配置好,一个特定的logger会附上一个handler。</span><span class="yiyi-st" id="yiyi-133">为了便于讨论,我们定义两个对象的连接中,logger是源头,handler是目的地。</span><span class="yiyi-st" id="yiyi-134">在配置好的对象中,这表示logger持有handler的一个引用。</span><span class="yiyi-st" id="yiyi-135">为了达到这个目的,在配置字典中每个目的对象都有一个id,独一无二的标识该对象,然后在源对象的配置中使用该id,表示源对象和id表示的目的对象间存在连接。</span></p><p><span class="yiyi-st" id="yiyi-136">所以拿下面的YAML代码片段为例:</span></p><div class="highlight-yaml"><div class="highlight"><pre><span></span><span class="l l-Scalar l-Scalar-Plain">formatters</span><span class="p p-Indicator">:</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">brief</span><span class="p p-Indicator">:</span>
|
||
<span class="c1"># configuration for formatter with id 'brief' goes here</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">precise</span><span class="p p-Indicator">:</span>
|
||
<span class="c1"># configuration for formatter with id 'precise' goes here</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">handlers</span><span class="p p-Indicator">:</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">h1</span><span class="p p-Indicator">:</span> <span class="c1">#This is an id</span>
|
||
<span class="c1"># configuration of handler with id 'h1' goes here</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">formatter</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">brief</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">h2</span><span class="p p-Indicator">:</span> <span class="c1">#This is another id</span>
|
||
<span class="c1"># configuration of handler with id 'h2' goes here</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">formatter</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">precise</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">loggers</span><span class="p p-Indicator">:</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">foo.bar.baz</span><span class="p p-Indicator">:</span>
|
||
<span class="c1"># other configuration for logger 'foo.bar.baz'</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">handlers</span><span class="p p-Indicator">:</span> <span class="p p-Indicator">[</span><span class="nv">h1</span><span class="p p-Indicator">,</span> <span class="nv">h2</span><span class="p p-Indicator">]</span>
|
||
</pre></div></div><p><span class="yiyi-st" id="yiyi-137">(注意:这里使用YAML是因为它比对应的Python的字典代码稍微更可读。)</span></p><p><span class="yiyi-st" id="yiyi-138">记录器的id是记录器名称,其将被编程地用于获得对这些记录器的引用,例如。</span><span class="yiyi-st" id="yiyi-139"><code class="docutils literal"><span class="pre">foo.bar.baz</span></code>。</span><span class="yiyi-st" id="yiyi-140">formatter和filter的id可以是任何的字符串(如上面的<code class="docutils literal"><span class="pre">brief</span></code>、<code class="docutils literal"><span class="pre">precise</span></code>)且是暂态的,意味着它们只在处理配置字典时有意义,用来决定对象间的连接,一旦配置结束,它们就不存在了。</span></p><p><span class="yiyi-st" id="yiyi-141">上述片段表示名为<code class="docutils literal"><span class="pre">foo.bar.baz</span></code>的logger附有两个handler,分别是id为<code class="docutils literal"><span class="pre">h1</span></code>和<code class="docutils literal"><span class="pre">h2</span></code>的handler来描述。</span><span class="yiyi-st" id="yiyi-142"><code class="docutils literal"><span class="pre">h1</span></code>的fotmatter由id为<code class="docutils literal"><span class="pre">brief</span></code>的formatter来描述,<code class="docutils literal"><span class="pre">h2</span></code>的formatter则是id为<code class="docutils literal"><span class="pre">precise</span></code>的formatter。</span></p></div><div class="section" id="user-defined-objects"><h3><span class="yiyi-st" id="yiyi-143">16.7.2.4. </span><span class="yiyi-st" id="yiyi-144">User-defined objects</span></h3><p><span class="yiyi-st" id="yiyi-145">该模式支持用户自定义handler、filter和formatter对象。</span><span class="yiyi-st" id="yiyi-146">(对于logger不需要不同的实例有不同的类型,所以该配置模式不支持用户定义的logger类。)</span></p><p><span class="yiyi-st" id="yiyi-147">对象的配置是由字典来具体描述的。</span><span class="yiyi-st" id="yiyi-148">某些情况下日志系统可以从上下文推断出如何实例化一个对象,但是当实例化一个用户定义的对象的时候,系统就不知道怎么做了。</span><span class="yiyi-st" id="yiyi-149">为了为用户定义的对象的实例化提供完整的弹性,用户需要提供一个‘工厂’——一个可调用对象,调用时以配置字典为参数,返回实例化的对象。</span><span class="yiyi-st" id="yiyi-150">这由键<code class="docutils literal"><span class="pre">'()'</span></code>及对应的工厂的绝对导入路径来表示。</span><span class="yiyi-st" id="yiyi-151">这里是个具体的例子:</span></p><div class="highlight-yaml"><div class="highlight"><pre><span></span><span class="l l-Scalar l-Scalar-Plain">formatters</span><span class="p p-Indicator">:</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">brief</span><span class="p p-Indicator">:</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">format</span><span class="p p-Indicator">:</span> <span class="s">'%(message)s'</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">default</span><span class="p p-Indicator">:</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">format</span><span class="p p-Indicator">:</span> <span class="s">'%(asctime)s</span><span class="nv"> </span><span class="s">%(levelname)-8s</span><span class="nv"> </span><span class="s">%(name)-15s</span><span class="nv"> </span><span class="s">%(message)s'</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">datefmt</span><span class="p p-Indicator">:</span> <span class="s">'%Y-%m-%d</span><span class="nv"> </span><span class="s">%H:%M:%S'</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">custom</span><span class="p p-Indicator">:</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">()</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">my.package.customFormatterFactory</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">bar</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">baz</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">spam</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">99.9</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">answer</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">42</span>
|
||
</pre></div></div><p><span class="yiyi-st" id="yiyi-152">上述YAML片段定义了三个formatter。</span><span class="yiyi-st" id="yiyi-153">第一个,标识<code class="docutils literal"><span class="pre">brief</span></code>,是具有指定格式字符串的标准<a class="reference internal" href="logging.html#logging.Formatter" title="logging.Formatter"><code class="xref py py-class docutils literal"><span class="pre">logging.Formatter</span></code></a>实例。</span><span class="yiyi-st" id="yiyi-154">第二个,id <code class="docutils literal"><span class="pre">default</span></code>,具有更长的格式,并且还显式地定义时间格式,并且将导致使用这两个格式字符串初始化<a class="reference internal" href="logging.html#logging.Formatter" title="logging.Formatter"><code class="xref py py-class docutils literal"><span class="pre">logging.Formatter</span></code></a>。</span><span class="yiyi-st" id="yiyi-155">以Python源码来看,formatter <code class="docutils literal"><span class="pre">brief</span></code>和<code class="docutils literal"><span class="pre">default</span></code>有配置子字典:</span></p><pre><code class="language-python"><span></span><span class="p">{</span>
|
||
<span class="s1">'format'</span> <span class="p">:</span> <span class="s1">'</span><span class="si">%(message)s</span><span class="s1">'</span>
|
||
<span class="p">}</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-156">和:</span></p><pre><code class="language-python"><span></span><span class="p">{</span>
|
||
<span class="s1">'format'</span> <span class="p">:</span> <span class="s1">'</span><span class="si">%(asctime)s</span><span class="s1"> </span><span class="si">%(levelname)-8s</span><span class="s1"> </span><span class="si">%(name)-15s</span><span class="s1"> </span><span class="si">%(message)s</span><span class="s1">'</span><span class="p">,</span>
|
||
<span class="s1">'datefmt'</span> <span class="p">:</span> <span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1"> %H:%M:%S'</span>
|
||
<span class="p">}</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-157">并且因为这些字典不包含特殊键<code class="docutils literal"><span class="pre">'()'</span></code>,所以从上下文推断出实例化:作为结果,创建标准<a class="reference internal" href="logging.html#logging.Formatter" title="logging.Formatter"><code class="xref py py-class docutils literal"><span class="pre">logging.Formatter</span></code></a>实例。</span><span class="yiyi-st" id="yiyi-158">第三个formatter的id为<code class="docutils literal"><span class="pre">custom</span></code>,其配置子字典是:</span></p><pre><code class="language-python"><span></span><span class="p">{</span>
|
||
<span class="s1">'()'</span> <span class="p">:</span> <span class="s1">'my.package.customFormatterFactory'</span><span class="p">,</span>
|
||
<span class="s1">'bar'</span> <span class="p">:</span> <span class="s1">'baz'</span><span class="p">,</span>
|
||
<span class="s1">'spam'</span> <span class="p">:</span> <span class="mf">99.9</span><span class="p">,</span>
|
||
<span class="s1">'answer'</span> <span class="p">:</span> <span class="mi">42</span>
|
||
<span class="p">}</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-159">它包含了特殊键<code class="docutils literal"><span class="pre">'()'</span></code>,意味着要实例化一个用户定义的对象。</span><span class="yiyi-st" id="yiyi-160">这种情况下,使用指定的工厂可调用对象。</span><span class="yiyi-st" id="yiyi-161">如果它是一个真的可调用对象就直接使用它,否则如果和例子中一样,指明了一个字符串,将通过常规的导入机制来确定真正的可调用对象。</span><span class="yiyi-st" id="yiyi-162">配置子字典中<strong>剩余的</strong>的项目会被当成关键字参数来调用可调用对象。</span><span class="yiyi-st" id="yiyi-163">上述例子中,id为<code class="docutils literal"><span class="pre">custom</span></code>的formatter会是下面调用的返回值:</span></p><pre><code class="language-python"><span></span><span class="n">my</span><span class="o">.</span><span class="n">package</span><span class="o">.</span><span class="n">customFormatterFactory</span><span class="p">(</span><span class="n">bar</span><span class="o">=</span><span class="s1">'baz'</span><span class="p">,</span> <span class="n">spam</span><span class="o">=</span><span class="mf">99.9</span><span class="p">,</span> <span class="n">answer</span><span class="o">=</span><span class="mi">42</span><span class="p">)</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-164">使用<code class="docutils literal"><span class="pre">'()'</span></code>作为特殊键是因为它不是个合法的关键字参数名,也就不会和调用时的关键字参数的名字冲突。</span><span class="yiyi-st" id="yiyi-165"><code class="docutils literal"><span class="pre">'()'</span></code>也用来表示对应值是个可调用对象。</span></p></div><div class="section" id="access-to-external-objects"><h3><span class="yiyi-st" id="yiyi-166">16.7.2.5. </span><span class="yiyi-st" id="yiyi-167">Access to external objects</span></h3><p><span class="yiyi-st" id="yiyi-168">偶尔配置需要引用外部对象,比如<code class="docutils literal"><span class="pre">sys.stderr</span></code>。</span><span class="yiyi-st" id="yiyi-169">如果配置dict是使用Python代码构造的,这是直接的,但是当通过文本文件(例如,文本文件)提供配置时出现问题。</span><span class="yiyi-st" id="yiyi-170">JSON,YAML)。</span><span class="yiyi-st" id="yiyi-171">在文本文件中,没有标准的方法来区分<code class="docutils literal"><span class="pre">sys.stderr</span></code>和字符串<code class="docutils literal"><span class="pre">'sys.stderr'</span></code>。</span><span class="yiyi-st" id="yiyi-172">为了区分,配置系统会在字符串值中查找特定的特殊前缀,并对其特殊对待。</span><span class="yiyi-st" id="yiyi-173">例如,如果配置值为<code class="docutils literal"><span class="pre">'ext://sys.stderr'</span></code>,<code class="docutils literal"><span class="pre">ext://</span></code>被移除,'sys.stderr'会被用来import。</span></p><p><span class="yiyi-st" id="yiyi-174">The handling of such prefixes is done in a way analogous to protocol handling: there is a generic mechanism to look for prefixes which match the regular expression <code class="docutils literal"><span class="pre">^(?P<prefix>[a-z]+)://(?P<suffix>.*)$</span></code> whereby, if the <code class="docutils literal"><span class="pre">prefix</span></code> is recognised, the <code class="docutils literal"><span class="pre">suffix</span></code> is processed in a prefix-dependent manner and the result of the processing replaces the string value. </span><span class="yiyi-st" id="yiyi-175">如果不识别prefix,则字符串的在值保持不变。</span></p></div><div class="section" id="access-to-internal-objects"><h3><span class="yiyi-st" id="yiyi-176">16.7.2.6. </span><span class="yiyi-st" id="yiyi-177">Access to internal objects</span></h3><p><span class="yiyi-st" id="yiyi-178">和外部对象一样,偶尔需要引用配置中的内部对象。</span><span class="yiyi-st" id="yiyi-179">如果配置系统知道这些对象,这就会隐式的完成。</span><span class="yiyi-st" id="yiyi-180">例如,记录器或处理程序中<code class="docutils literal"><span class="pre">level</span></code>的字符串值<code class="docutils literal"><span class="pre">'DEBUG'</span></code>将自动转换为值<code class="docutils literal"><span class="pre">logging.DEBUG</span></code>, <code class="docutils literal"><span class="pre">handlers</span></code>,<code class="docutils literal"><span class="pre">filters</span></code>和<code class="docutils literal"><span class="pre">formatter</span></code>条目将获取对象标识并解析为适当的目标对象。</span></p><p><span class="yiyi-st" id="yiyi-181">然而对于不知道<a class="reference internal" href="logging.html#module-logging" title="logging: Flexible event logging system for applications."><code class="xref py py-mod docutils literal"><span class="pre">logging</span></code></a>模块的用户定义的对象来说就需要一个更通用的机制。</span><span class="yiyi-st" id="yiyi-182">考虑<a class="reference internal" href="logging.handlers.html#logging.handlers.MemoryHandler" title="logging.handlers.MemoryHandler"><code class="xref py py-class docutils literal"><span class="pre">logging.handlers.MemoryHandler</span></code></a>,它有<code class="docutils literal"><span class="pre">target</span></code>参数,是另一个handler的代理。</span><span class="yiyi-st" id="yiyi-183">既然系统知道此类,配置中对于<code class="docutils literal"><span class="pre">target</span></code>只要给出相关目标handler的对象id,系统会根据id解析出对应的handler对象。</span><span class="yiyi-st" id="yiyi-184">然而对于用户定义的<code class="docutils literal"><span class="pre">my.package.MyHandler</span></code>,它有一个<code class="docutils literal"><span class="pre">alternate</span></code> handler,系统就不知道<code class="docutils literal"><span class="pre">alternate</span></code>引用handler。</span><span class="yiyi-st" id="yiyi-185">为了满足此场景,通用的解析系统允许用户指定:</span></p><pre><code class="language-python"><span></span><span class="n">handlers</span><span class="p">:</span>
|
||
<span class="n">file</span><span class="p">:</span>
|
||
<span class="c1"># configuration of file handler goes here</span>
|
||
|
||
<span class="n">custom</span><span class="p">:</span>
|
||
<span class="p">():</span> <span class="n">my</span><span class="o">.</span><span class="n">package</span><span class="o">.</span><span class="n">MyHandler</span>
|
||
<span class="n">alternate</span><span class="p">:</span> <span class="n">cfg</span><span class="p">:</span><span class="o">//</span><span class="n">handlers</span><span class="o">.</span><span class="n">file</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-186">字符串<code class="docutils literal"><span class="pre">'cfg://handlers.file'</span></code>的解析类比于<code class="docutils literal"><span class="pre">ext://</span></code>的前缀处理,只是查找配置本身而不是导入空间。</span><span class="yiyi-st" id="yiyi-187">该机制允许点/索引访问,类似于<code class="docutils literal"><span class="pre">str.format</span></code>。</span><span class="yiyi-st" id="yiyi-188">因此给定下述片段:</span></p><pre><code class="language-python"><span></span><span class="n">handlers</span><span class="p">:</span>
|
||
<span class="n">email</span><span class="p">:</span>
|
||
<span class="n">class</span><span class="p">:</span> <span class="n">logging</span><span class="o">.</span><span class="n">handlers</span><span class="o">.</span><span class="n">SMTPHandler</span>
|
||
<span class="n">mailhost</span><span class="p">:</span> <span class="n">localhost</span>
|
||
<span class="n">fromaddr</span><span class="p">:</span> <span class="n">my_app</span><span class="nd">@domain</span><span class="o">.</span><span class="n">tld</span>
|
||
<span class="n">toaddrs</span><span class="p">:</span>
|
||
<span class="o">-</span> <span class="n">support_team</span><span class="nd">@domain</span><span class="o">.</span><span class="n">tld</span>
|
||
<span class="o">-</span> <span class="n">dev_team</span><span class="nd">@domain</span><span class="o">.</span><span class="n">tld</span>
|
||
<span class="n">subject</span><span class="p">:</span> <span class="n">Houston</span><span class="p">,</span> <span class="n">we</span> <span class="n">have</span> <span class="n">a</span> <span class="n">problem</span><span class="o">.</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-189">配置中字符串<code class="docutils literal"><span class="pre">'cfg://handlers'</span></code>解析成键为<code class="docutils literal"><span class="pre">handlers</span></code>的字典;字符串<code class="docutils literal"><span class="pre">'cfg://handlers.email</span></code>解析成<code class="docutils literal"><span class="pre">email</span></code>字典中键为<code class="docutils literal"><span class="pre">handlers</span></code>的字典;依此类推。</span><span class="yiyi-st" id="yiyi-190">字符串<code class="docutils literal"><span class="pre">'cfg://handlers.email.toaddrs[1]</span></code>解析成<code class="docutils literal"><span class="pre">'dev_team.domain.tld'</span></code>;字符串 <code class="docutils literal"><span class="pre">'cfg://handlers.email.toaddrs[0]'</span></code>解析成<code class="docutils literal"><span class="pre">'support_team@domain.tld'</span></code>。</span><span class="yiyi-st" id="yiyi-191">可以通过<code class="docutils literal"><span class="pre">subject</span></code>或者<code class="docutils literal"><span class="pre">'cfg://handlers.email.subject'</span></code>来访问<code class="docutils literal"><span class="pre">'cfg://handlers.email[subject]'</span></code>的值。</span><span class="yiyi-st" id="yiyi-192">如果键中包含空格或者非字母数字字符时才需要后面一种形式。</span><span class="yiyi-st" id="yiyi-193">如果索引值只包含数字,将先尝试用对应的整数值来访问,然后才是用字符串来访问。</span></p><p><span class="yiyi-st" id="yiyi-194">给定字符串<code class="docutils literal"><span class="pre">cfg://handlers.myhandler.mykey.123</span></code>,它将被解析成<code class="docutils literal"><span class="pre">config_dict['handlers']['myhandler']['mykey']['123']</span></code>。</span><span class="yiyi-st" id="yiyi-195">如果是<code class="docutils literal"><span class="pre">cfg://handlers.myhandler.mykey[123]</span></code>,系统先尝试<code class="docutils literal"><span class="pre">config_dict['handlers']['myhandler']['mykey'][123]</span></code>,如果尝试失败再尝试<code class="docutils literal"><span class="pre">config_dict['handlers']['myhandler']['mykey']['123']</span></code>。</span></p></div><div class="section" id="import-resolution-and-custom-importers"><h3><span class="yiyi-st" id="yiyi-196">16.7.2.7. </span><span class="yiyi-st" id="yiyi-197">Import resolution and custom importers</span></h3><p><span class="yiyi-st" id="yiyi-198">导入默认使用内置的<a class="reference internal" href="functions.html#__import__" title="__import__"><code class="xref py py-func docutils literal"><span class="pre">__import__()</span></code></a>函数。</span><span class="yiyi-st" id="yiyi-199">也许希望使用自己的导入机制:如果是这样,替换<code class="xref py py-attr docutils literal"><span class="pre">importer</span></code>或者其超类<code class="xref py py-class docutils literal"><span class="pre">DictConfigurator</span></code>的<code class="xref py py-class docutils literal"><span class="pre">BaseConfigurator</span></code>属性。</span><span class="yiyi-st" id="yiyi-200">然而从类的描述符访问函数时要小心。</span><span class="yiyi-st" id="yiyi-201">如果使用Python可调用对象来做导入,而且希望在类级别而不是实例级别来定义它,使用<a class="reference internal" href="functions.html#staticmethod" title="staticmethod"><code class="xref py py-func docutils literal"><span class="pre">staticmethod()</span></code></a>包装它。</span><span class="yiyi-st" id="yiyi-202">例如:</span></p><pre><code class="language-python"><span></span><span class="kn">from</span> <span class="nn">importlib</span> <span class="k">import</span> <span class="n">import_module</span>
|
||
<span class="kn">from</span> <span class="nn">logging.config</span> <span class="k">import</span> <span class="n">BaseConfigurator</span>
|
||
|
||
<span class="n">BaseConfigurator</span><span class="o">.</span><span class="n">importer</span> <span class="o">=</span> <span class="nb">staticmethod</span><span class="p">(</span><span class="n">import_module</span><span class="p">)</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-203">如果在配置器<em>实例</em>上设置导入可调用对象,不需要用<a class="reference internal" href="functions.html#staticmethod" title="staticmethod"><code class="xref py py-func docutils literal"><span class="pre">staticmethod()</span></code></a>来包装它。</span></p></div></div><div class="section" id="configuration-file-format"><h2><span class="yiyi-st" id="yiyi-204">16.7.3. </span><span class="yiyi-st" id="yiyi-205">Configuration file format</span></h2><p><span class="yiyi-st" id="yiyi-206"><a class="reference internal" href="#logging.config.fileConfig" title="logging.config.fileConfig"><code class="xref py py-func docutils literal"><span class="pre">fileConfig()</span></code></a>理解的配置文件格式基于<a class="reference internal" href="configparser.html#module-configparser" title="configparser: Configuration file parser."><code class="xref py py-mod docutils literal"><span class="pre">configparser</span></code></a>的功能。</span><span class="yiyi-st" id="yiyi-207">文件必需包含名为<code class="docutils literal"><span class="pre">[loggers]</span></code>, <code class="docutils literal"><span class="pre">[handlers]</span></code> 和 <code class="docutils literal"><span class="pre">[formatters]</span></code>的节,标识了文件中定义的各种类型的对象的名字。</span><span class="yiyi-st" id="yiyi-208">对于每一个实体,有一个独立的节标识如何配置该实体。</span><span class="yiyi-st" id="yiyi-209"><code class="docutils literal"><span class="pre">log01</span></code>节中有名为<code class="docutils literal"><span class="pre">[loggers]</span></code>的logger,<code class="docutils literal"><span class="pre">[logger_log01]</span></code>的节中包含了相关的配置细节。</span><span class="yiyi-st" id="yiyi-210">类似的,<code class="docutils literal"><span class="pre">hand01</span></code>节中有名为<code class="docutils literal"><span class="pre">[handlers]</span></code>的handler,<code class="docutils literal"><span class="pre">[handler_hand01]</span></code>节中包含了相关的配置;<code class="docutils literal"><span class="pre">form01</span></code>节中有名为<code class="docutils literal"><span class="pre">[formatters]</span></code>的formatter,<code class="docutils literal"><span class="pre">[formatter_form01]</span></code>节中包含了相关的配置。</span><span class="yiyi-st" id="yiyi-211"><code class="docutils literal"><span class="pre">[logger_root]</span></code>节中包含了根logger的配置。</span></p><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-212">注意</span></p><p class="last"><span class="yiyi-st" id="yiyi-213"><a class="reference internal" href="#logging.config.fileConfig" title="logging.config.fileConfig"><code class="xref py py-func docutils literal"><span class="pre">fileConfig()</span></code></a> API比<a class="reference internal" href="#logging.config.dictConfig" title="logging.config.dictConfig"><code class="xref py py-func docutils literal"><span class="pre">dictConfig()</span></code></a> API旧,并且不提供涵盖日志记录某些方面的功能。</span><span class="yiyi-st" id="yiyi-214">例如,您无法使用<a class="reference internal" href="#logging.config.fileConfig" title="logging.config.fileConfig"><code class="xref py py-func docutils literal"><span class="pre">fileConfig()</span></code></a>配置<a class="reference internal" href="logging.html#logging.Filter" title="logging.Filter"><code class="xref py py-class docutils literal"><span class="pre">Filter</span></code></a>对象,该对象提供对超过简单整数级别的消息的过滤。</span><span class="yiyi-st" id="yiyi-215">如果您需要在日志配置中具有<a class="reference internal" href="logging.html#logging.Filter" title="logging.Filter"><code class="xref py py-class docutils literal"><span class="pre">Filter</span></code></a>的实例,则需要使用<a class="reference internal" href="#logging.config.dictConfig" title="logging.config.dictConfig"><code class="xref py py-func docutils literal"><span class="pre">dictConfig()</span></code></a>。</span><span class="yiyi-st" id="yiyi-216">请注意,配置功能的未来增强功能将添加到<a class="reference internal" href="#logging.config.dictConfig" title="logging.config.dictConfig"><code class="xref py py-func docutils literal"><span class="pre">dictConfig()</span></code></a>中,因此,当这样做很方便时,值得考虑转换到这个较新的API。</span></p></div><p><span class="yiyi-st" id="yiyi-217">这些节的例子给定如下。</span></p><div class="highlight-ini"><div class="highlight"><pre><span></span><span class="k">[loggers]</span>
|
||
<span class="na">keys</span><span class="o">=</span><span class="s">root,log02,log03,log04,log05,log06,log07</span>
|
||
|
||
<span class="k">[handlers]</span>
|
||
<span class="na">keys</span><span class="o">=</span><span class="s">hand01,hand02,hand03,hand04,hand05,hand06,hand07,hand08,hand09</span>
|
||
|
||
<span class="k">[formatters]</span>
|
||
<span class="na">keys</span><span class="o">=</span><span class="s">form01,form02,form03,form04,form05,form06,form07,form08,form09</span>
|
||
</pre></div></div><p><span class="yiyi-st" id="yiyi-218">根logger必需指定级别和handler列表。</span><span class="yiyi-st" id="yiyi-219">根logger节的例子给定如下。</span></p><div class="highlight-ini"><div class="highlight"><pre><span></span><span class="k">[logger_root]</span>
|
||
<span class="na">level</span><span class="o">=</span><span class="s">NOTSET</span>
|
||
<span class="na">handlers</span><span class="o">=</span><span class="s">hand01</span>
|
||
</pre></div></div><p><span class="yiyi-st" id="yiyi-220"><code class="docutils literal"><span class="pre">level</span></code>可以是<code class="docutils literal"><span class="pre">DEBUG,</span> <span class="pre">INFO,</span> <span class="pre">WARNING,</span> <span class="pre">ERROR,</span> <span class="pre">CRITICAL</span></code> 或 <code class="docutils literal"><span class="pre">NOTSET</span></code>其中之一。</span><span class="yiyi-st" id="yiyi-221"><code class="docutils literal"><span class="pre">NOTSET</span></code>表示所有的消息都要记录,这只对根logger有效。</span><span class="yiyi-st" id="yiyi-222">级别值使用<a class="reference internal" href="functions.html#eval" title="eval"><code class="xref py py-func docutils literal"><span class="pre">eval()</span></code></a>在<code class="docutils literal"><span class="pre">logging</span></code>包空间演算得到。</span></p><p><span class="yiyi-st" id="yiyi-223"><code class="docutils literal"><span class="pre">handlers</span></code>是逗号分隔的handler名字的列表,这些必需出现在<code class="docutils literal"><span class="pre">[handlers]</span></code>节中。</span><span class="yiyi-st" id="yiyi-224">这些名字必需出现在<code class="docutils literal"><span class="pre">[handlers]</span></code>节中,且在配置文件中有对应的节。</span></p><p><span class="yiyi-st" id="yiyi-225">对于非根logger的logger来说,需要一些额外的信息。</span><span class="yiyi-st" id="yiyi-226">如下例所示。</span></p><div class="highlight-ini"><div class="highlight"><pre><span></span><span class="k">[logger_parser]</span>
|
||
<span class="na">level</span><span class="o">=</span><span class="s">DEBUG</span>
|
||
<span class="na">handlers</span><span class="o">=</span><span class="s">hand01</span>
|
||
<span class="na">propagate</span><span class="o">=</span><span class="s">1</span>
|
||
<span class="na">qualname</span><span class="o">=</span><span class="s">compiler.parser</span>
|
||
</pre></div></div><p><span class="yiyi-st" id="yiyi-227"><code class="docutils literal"><span class="pre">level</span></code> 和 <code class="docutils literal"><span class="pre">handlers</span></code> 的解读和根logger的一样,如果非根logger的级别为<code class="docutils literal"><span class="pre">NOTSET</span></code>,系统参考高层次的logger来决定logger的有效级别。</span><span class="yiyi-st" id="yiyi-228"><code class="docutils literal"><span class="pre">propagate</span></code>为1表示将消息传递给高层次logger的handler,为0表示<strong>不</strong>传播。</span><span class="yiyi-st" id="yiyi-229"><code class="docutils literal"><span class="pre">qualname</span></code>是logger在层次中的名字,应用通过该名字得到logger。</span></p><p><span class="yiyi-st" id="yiyi-230">handler配置节如下所示。</span></p><div class="highlight-ini"><div class="highlight"><pre><span></span><span class="k">[handler_hand01]</span>
|
||
<span class="na">class</span><span class="o">=</span><span class="s">StreamHandler</span>
|
||
<span class="na">level</span><span class="o">=</span><span class="s">NOTSET</span>
|
||
<span class="na">formatter</span><span class="o">=</span><span class="s">form01</span>
|
||
<span class="na">args</span><span class="o">=</span><span class="s">(sys.stdout,)</span>
|
||
</pre></div></div><p><span class="yiyi-st" id="yiyi-231"><code class="docutils literal"><span class="pre">logging</span></code>表示handler的类(在<code class="docutils literal"><span class="pre">class</span></code>包空间中通过<a class="reference internal" href="functions.html#eval" title="eval"><code class="xref py py-func docutils literal"><span class="pre">eval()</span></code></a>演算得到。)</span><span class="yiyi-st" id="yiyi-232"><code class="docutils literal"><span class="pre">level</span></code>的解读和logger的一样,<code class="docutils literal"><span class="pre">NOTSET</span></code>表示‘记录所有日志’。</span></p><p><span class="yiyi-st" id="yiyi-233"><code class="docutils literal"><span class="pre">formatter</span></code>表示了该handler的formatter的名字。</span><span class="yiyi-st" id="yiyi-234">如果为空,使用默认formatter (<code class="docutils literal"><span class="pre">logging._defaultFormatter</span></code>)。</span><span class="yiyi-st" id="yiyi-235">如果指定了名字,它必需出现在<code class="docutils literal"><span class="pre">[formatters]</span></code>节中,且在配置文件中有对应的节。</span></p><p><span class="yiyi-st" id="yiyi-236"><code class="docutils literal"><span class="pre">logging</span></code>是handler类构造函数的参数列表(在<code class="docutils literal"><span class="pre">args</span></code>包空间通过<a class="reference internal" href="functions.html#eval" title="eval"><code class="xref py py-func docutils literal"><span class="pre">eval()</span></code></a>演算得到)。</span><span class="yiyi-st" id="yiyi-237">参考相关handler的构造函数,或者参考下面的例子,以了解典型的构造。</span></p><div class="highlight-ini"><div class="highlight"><pre><span></span><span class="k">[handler_hand02]</span>
|
||
<span class="na">class</span><span class="o">=</span><span class="s">FileHandler</span>
|
||
<span class="na">level</span><span class="o">=</span><span class="s">DEBUG</span>
|
||
<span class="na">formatter</span><span class="o">=</span><span class="s">form02</span>
|
||
<span class="na">args</span><span class="o">=</span><span class="s">('python.log', 'w')</span>
|
||
|
||
<span class="k">[handler_hand03]</span>
|
||
<span class="na">class</span><span class="o">=</span><span class="s">handlers.SocketHandler</span>
|
||
<span class="na">level</span><span class="o">=</span><span class="s">INFO</span>
|
||
<span class="na">formatter</span><span class="o">=</span><span class="s">form03</span>
|
||
<span class="na">args</span><span class="o">=</span><span class="s">('localhost', handlers.DEFAULT_TCP_LOGGING_PORT)</span>
|
||
|
||
<span class="k">[handler_hand04]</span>
|
||
<span class="na">class</span><span class="o">=</span><span class="s">handlers.DatagramHandler</span>
|
||
<span class="na">level</span><span class="o">=</span><span class="s">WARN</span>
|
||
<span class="na">formatter</span><span class="o">=</span><span class="s">form04</span>
|
||
<span class="na">args</span><span class="o">=</span><span class="s">('localhost', handlers.DEFAULT_UDP_LOGGING_PORT)</span>
|
||
|
||
<span class="k">[handler_hand05]</span>
|
||
<span class="na">class</span><span class="o">=</span><span class="s">handlers.SysLogHandler</span>
|
||
<span class="na">level</span><span class="o">=</span><span class="s">ERROR</span>
|
||
<span class="na">formatter</span><span class="o">=</span><span class="s">form05</span>
|
||
<span class="na">args</span><span class="o">=</span><span class="s">(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER)</span>
|
||
|
||
<span class="k">[handler_hand06]</span>
|
||
<span class="na">class</span><span class="o">=</span><span class="s">handlers.NTEventLogHandler</span>
|
||
<span class="na">level</span><span class="o">=</span><span class="s">CRITICAL</span>
|
||
<span class="na">formatter</span><span class="o">=</span><span class="s">form06</span>
|
||
<span class="na">args</span><span class="o">=</span><span class="s">('Python Application', '', 'Application')</span>
|
||
|
||
<span class="k">[handler_hand07]</span>
|
||
<span class="na">class</span><span class="o">=</span><span class="s">handlers.SMTPHandler</span>
|
||
<span class="na">level</span><span class="o">=</span><span class="s">WARN</span>
|
||
<span class="na">formatter</span><span class="o">=</span><span class="s">form07</span>
|
||
<span class="na">args</span><span class="o">=</span><span class="s">('localhost', 'from@abc', ['user1@abc', 'user2@xyz'], 'Logger Subject')</span>
|
||
|
||
<span class="k">[handler_hand08]</span>
|
||
<span class="na">class</span><span class="o">=</span><span class="s">handlers.MemoryHandler</span>
|
||
<span class="na">level</span><span class="o">=</span><span class="s">NOTSET</span>
|
||
<span class="na">formatter</span><span class="o">=</span><span class="s">form08</span>
|
||
<span class="na">target</span><span class="o">=</span>
|
||
<span class="na">args</span><span class="o">=</span><span class="s">(10, ERROR)</span>
|
||
|
||
<span class="k">[handler_hand09]</span>
|
||
<span class="na">class</span><span class="o">=</span><span class="s">handlers.HTTPHandler</span>
|
||
<span class="na">level</span><span class="o">=</span><span class="s">NOTSET</span>
|
||
<span class="na">formatter</span><span class="o">=</span><span class="s">form09</span>
|
||
<span class="na">args</span><span class="o">=</span><span class="s">('localhost:9022', '/log', 'GET')</span>
|
||
</pre></div></div><p><span class="yiyi-st" id="yiyi-238">指定了格式化配置的节典型如下。</span></p><div class="highlight-ini"><div class="highlight"><pre><span></span><span class="k">[formatter_form01]</span>
|
||
<span class="na">format</span><span class="o">=</span><span class="s">F1 %(asctime)s %(levelname)s %(message)s</span>
|
||
<span class="na">datefmt</span><span class="o">=</span>
|
||
<span class="na">class</span><span class="o">=</span><span class="s">logging.Formatter</span>
|
||
</pre></div></div><p><span class="yiyi-st" id="yiyi-239"><code class="docutils literal"><span class="pre">format</span></code>是整体的格式化字符串,<code class="docutils literal"><span class="pre">datefmt</span></code>是<code class="xref py py-func docutils literal"><span class="pre">strftime()</span></code>兼容的日期/时间格式化字符串。</span><span class="yiyi-st" id="yiyi-240">如果为空,使用ISO8601格式,基本上等同于格式<code class="docutils literal"><span class="pre">'%Y-%m-%d</span> <span class="pre">%H:%M:%S'</span></code>。</span><span class="yiyi-st" id="yiyi-241">ISO8601格式在上述格式的末尾指明了毫秒,中间有个逗号。</span><span class="yiyi-st" id="yiyi-242">ISO8601格式的例子:<code class="docutils literal"><span class="pre">2003-01-23</span> <span class="pre">00:29:50,411</span></code>。</span></p><p><span class="yiyi-st" id="yiyi-243"><code class="docutils literal"><span class="pre">class</span></code>可选。</span><span class="yiyi-st" id="yiyi-244">它表示formatter类的名字(带点的模块和类名)。</span><span class="yiyi-st" id="yiyi-245">实例化<a class="reference internal" href="logging.html#logging.Formatter" title="logging.Formatter"><code class="xref py py-class docutils literal"><span class="pre">Formatter</span></code></a>子类时该选项很有用。</span><span class="yiyi-st" id="yiyi-246"><a class="reference internal" href="logging.html#logging.Formatter" title="logging.Formatter"><code class="xref py py-class docutils literal"><span class="pre">Formatter</span></code></a>子类可以用来表示详细/概要的异常回溯。</span></p><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-247">注意</span></p><p class="last"><span class="yiyi-st" id="yiyi-248">如上所述由于使用了<a class="reference internal" href="functions.html#eval" title="eval"><code class="xref py py-func docutils literal"><span class="pre">eval()</span></code></a>,如果使用<a class="reference internal" href="#logging.config.listen" title="logging.config.listen"><code class="xref py py-func docutils literal"><span class="pre">listen()</span></code></a>来通过套接字发送和接受配置,这会导致潜在的安全风险。</span><span class="yiyi-st" id="yiyi-249">风险限于多个没有相互信任的用户在同一台机器上运行代码的地方;有关详细信息,请参阅<a class="reference internal" href="#logging.config.listen" title="logging.config.listen"><code class="xref py py-func docutils literal"><span class="pre">listen()</span></code></a>文档。</span></p></div><div class="admonition seealso"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-250">参见</span></p><dl class="last docutils"><dt><span class="yiyi-st" id="yiyi-251">模块<a class="reference internal" href="logging.html#module-logging" title="logging: Flexible event logging system for applications."><code class="xref py py-mod docutils literal"><span class="pre">logging</span></code></a></span></dt><dd><span class="yiyi-st" id="yiyi-252">日志模块的API参考。</span></dd><dt><span class="yiyi-st" id="yiyi-253">模块<a class="reference internal" href="logging.handlers.html#module-logging.handlers" title="logging.handlers: Handlers for the logging module."><code class="xref py py-mod docutils literal"><span class="pre">logging.handlers</span></code></a></span></dt><dd><span class="yiyi-st" id="yiyi-254">日志模块所带的有用的handler。</span></dd></dl></div></div></div></div> |