<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Logging | Haobin Tan</title><link>https://haobin-tan.netlify.app/tags/logging/</link><atom:link href="https://haobin-tan.netlify.app/tags/logging/index.xml" rel="self" type="application/rss+xml"/><description>Logging</description><generator>Hugo Blox Builder (https://hugoblox.com)</generator><language>en-us</language><lastBuildDate>Thu, 16 Feb 2023 00:00:00 +0000</lastBuildDate><image><url>https://haobin-tan.netlify.app/media/icon_hu7d15bc7db65c8eaf7a4f66f5447d0b42_15095_512x512_fill_lanczos_center_3.png</url><title>Logging</title><link>https://haobin-tan.netlify.app/tags/logging/</link></image><item><title>Logging</title><link>https://haobin-tan.netlify.app/docs/coding/python/useful_packages/logging/</link><pubDate>Wed, 11 Jan 2023 00:00:00 +0000</pubDate><guid>https://haobin-tan.netlify.app/docs/coding/python/useful_packages/logging/</guid><description>&lt;p>Logging is a very useful tool in a programmer’s toolbox.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>It helps you develop a better understanding of the flow of a program&lt;/p>
&lt;/li>
&lt;li>
&lt;p>It helps you discover scenarios that you might not even have thought of while developing&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>Logs&lt;/p>
&lt;ul>
&lt;li>
&lt;p>provide developers with an extra set of eyes that are constantly looking at the flow that an application is going through&lt;/p>
&lt;/li>
&lt;li>
&lt;p>can store information&lt;/p>
&lt;/li>
&lt;li>
&lt;p>If an error occurs, can provide more insights than a stack trace by telling you what the state of the program was before it arrived at the line of code where the error occurred.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="the-logging-module">The Logging Module&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">logging&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>5 standard levels indicating the severity of events (in the increasing order)&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">Logging level&lt;/th>
&lt;th>Value&lt;/th>
&lt;th style="text-align:left">Usage&lt;/th>
&lt;th style="text-align:left">Possible message output&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Debug&lt;/strong>&lt;/td>
&lt;td>10&lt;/td>
&lt;td style="text-align:left">Problem diagnosis, very detailed&lt;/td>
&lt;td style="text-align:left">Unexpected indentation in line XY&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Info&lt;/strong>&lt;/td>
&lt;td>20&lt;/td>
&lt;td style="text-align:left">Gives feedback stating that the system is running properly&lt;/td>
&lt;td style="text-align:left">Function 1*1 is executed&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Warning&lt;/strong>&lt;/td>
&lt;td>30&lt;/td>
&lt;td style="text-align:left">The application is working properly to the greatest possible extent, but an unexpected situation has occurred or a warning has been issued about a future problem&lt;/td>
&lt;td style="text-align:left">Storage space becomes scarce&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Error&lt;/strong>&lt;/td>
&lt;td>40&lt;/td>
&lt;td style="text-align:left">A function could not be executed because a problem occurred&lt;/td>
&lt;td style="text-align:left">An error occurred and the action was canceled&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Critical&lt;/strong>&lt;/td>
&lt;td>50&lt;/td>
&lt;td style="text-align:left">A serious problem has occurred and the entire application may need to be stopped&lt;/td>
&lt;td style="text-align:left">Serious error: The program cannot access this service and must be terminated&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;img src="https://raw.githubusercontent.com/EckoTan0804/upic-repo/master/uPic/1*aHKt_H9yzoU_gcSlfQgDpQ.png" alt="">&lt;/p>
&lt;p>Logging with default logger:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">logging&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">debug&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;This is a debug message&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;This is an info message&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">warning&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;This is a warning message&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">error&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;This is an error message&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">critical&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;This is a critical message&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Output:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">WARNING:root:This is a warning message
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ERROR:root:This is an error message
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">CRITICAL:root:This is a critical message
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>
&lt;p>Default output format: evel, name, and message separated by a colon (&lt;code>:&lt;/code>)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>The &lt;code>debug()&lt;/code> and &lt;code>info()&lt;/code> messages didn’t get logged.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>By default, the logging module logs the messages with a severity level of &lt;code>WARNING&lt;/code> or above.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>You can change that by configuring the logging module to log events of all levels if you want.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="basic-configurations">Basic Configurations&lt;/h2>
&lt;p>You can use the &lt;code>basicConfig(**kwargs)&lt;/code> method to configure the logging. Some of the commonly used parameters for &lt;code>basicConfig()&lt;/code> are:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;code>level&lt;/code>: The root logger will be set to the specified severity level.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">logging&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">basicConfig&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">level&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DEBUG&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">debug&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;This will get logged&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">DEBUG:root:This will get logged
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;code>filename&lt;/code>: file where the log information will be output to&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>filemode&lt;/code>: If &lt;code>filename&lt;/code> is given, the file is opened in this mode. The default mode is &lt;code>a&lt;/code> (append).&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>format&lt;/code>: format of the log message.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">logging&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">basicConfig&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">filename&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;app.log&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">filemode&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;w&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">format&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="si">%(name)s&lt;/span>&lt;span class="s1"> - &lt;/span>&lt;span class="si">%(levelname)s&lt;/span>&lt;span class="s1"> - &lt;/span>&lt;span class="si">%(message)s&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># The log message will be ouput to `app.log`&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">warning&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;This will get logged to a file&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;p>More parameters can be found &lt;a href="https://docs.python.org/3/library/logging.html#logging.basicConfig">here&lt;/a>.&lt;/p>
&lt;p>Note: calling &lt;code>basicConfig()&lt;/code> to configure the root logger works only if the root logger has not been configured before. &lt;strong>Basically, this function can only be called once.&lt;/strong>&lt;/p>
&lt;h2 id="formatting-the-output">Formatting the Output&lt;/h2>
&lt;p>There are some basic elements that are already a part of the &lt;code>LogRecord&lt;/code> and can be easily added to the output format, e.g.,&lt;/p>
&lt;ul>
&lt;li>
&lt;p>asctime &lt;code>%(asctime)s&lt;/code>&lt;/p>
&lt;ul>
&lt;li>The format can be changed using the &lt;code>datefmt&lt;/code> attribute, which uses the same formatting language as the formatting functions in the datetime module&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>message &lt;code>%(message)s&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>name&lt;code>%(name)s&lt;/code>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>The entire list of available attributes can be found &lt;a href="https://docs.python.org/3/library/logging.html#logrecord-attributes">here&lt;/a>.&lt;/p>
&lt;p>Example:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">basicConfig&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">level&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DEBUG&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">format&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;[%(asctime)s] - %(levelname)s - %(message)s&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">datefmt&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;%Y-%m-&lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s2"> %H:%M:%S&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;User log in&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>2023-01-11 13:50:25&lt;span class="o">]&lt;/span> - INFO - User log in
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="logging-variable-data">Logging Variable Data&lt;/h3>
&lt;p>Logging methods take a string as an argument $\rightarrow$ We can format a string with variable data using f-string.&lt;/p>
&lt;p>Example:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">user_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;John&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">basicConfig&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">level&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DEBUG&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># filename=&amp;#34;test.log&amp;#34;,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># filemode=&amp;#34;w&amp;#34;,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">format&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;[%(asctime)s] - %(levelname)s - %(message)s&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">datefmt&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;%Y-%m-&lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s2"> %H:%M:%S&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">user_name&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> log in&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>2023-01-11 13:55:23&lt;span class="o">]&lt;/span> - INFO - John log in
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="capturing-stack-traces">Capturing Stack Traces&lt;/h3>
&lt;p>The logging module also allows you to capture the full stack traces in an application. &lt;a href="https://realpython.com/python-exceptions/">Exception information&lt;/a> can be captured if the &lt;code>exc_info&lt;/code> parameter is passed as &lt;code>True&lt;/code>.&lt;/p>
&lt;p>Example:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">logging&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">c&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">b&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">except&lt;/span> &lt;span class="ne">Exception&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">error&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Exception occurred&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">exc_info&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">ERROR:root:Exception occurred
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Traceback &lt;span class="o">(&lt;/span>most recent call last&lt;span class="o">)&lt;/span>:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> File &lt;span class="s2">&amp;#34;exceptions.py&amp;#34;&lt;/span>, line 6, in &amp;lt;module&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">c&lt;/span> &lt;span class="o">=&lt;/span> a / b
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ZeroDivisionError: division by zero
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If &lt;code>exc_info&lt;/code> is not set to &lt;code>True&lt;/code>, the output of the above program would not tell us anything about the exception.&lt;/p>
&lt;p>If you’re logging from an exception handler, use the &lt;code>logging.exception()&lt;/code> method, which logs a message with level &lt;code>ERROR&lt;/code> and adds exception information to the message. Calling &lt;code>logging.exception()&lt;/code> is like calling &lt;code>logging.error(exc_info=True)&lt;/code>, which always dumps exception information.&lt;/p>
&lt;h2 id="classes-and-functions">Classes and Functions&lt;/h2>
&lt;p>You can (and should) define your own logger by &lt;a href="https://realpython.com/python3-object-oriented-programming/">creating an object&lt;/a> of the &lt;code>Logger&lt;/code> class, especially if your application has multiple modules.&lt;/p>
&lt;p>The most commonly used classes defined in the logging module are:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>&lt;code>Logger&lt;/code>:&lt;/strong> the class whose objects will be used in the application code directly to call the functions.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>&lt;code>LogRecord&lt;/code>&lt;/strong>: Loggers automatically create &lt;code>LogRecord&lt;/code> objects that have all the information related to the event being logged, like the name of the logger, the function, the line number, the message, and more.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>&lt;code>Handler&lt;/code>:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Send the &lt;code>LogRecord&lt;/code> to the required output destination, like the console or a file.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>Handler&lt;/code> is a base for subclasses like &lt;code>StreamHandler&lt;/code>, &lt;code>FileHandler&lt;/code>, &lt;code>SMTPHandler&lt;/code>, &lt;code>HTTPHandler&lt;/code>, and more. These subclasses send the logging outputs to corresponding destinations.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>&lt;code>Formatter&lt;/code>:&lt;/strong> specify the format of the output by specifying a string format that lists out the attributes that the output should contain.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>&lt;code>Filters&lt;/code>&lt;/strong>: provide a finer grained facility for determining which log records to output.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>We mostly deal with the objects of the &lt;code>Logger&lt;/code> class, which are instantiated using the module-level function &lt;code>logging.getLogger(name)&lt;/code>. Multiple calls to &lt;code>getLogger()&lt;/code> with the same &lt;code>name&lt;/code> will return a reference to the same &lt;code>Logger&lt;/code> object, which saves us from passing the logger objects to every part where it’s needed.&lt;/p>
&lt;p>Example:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">logging&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logger&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getLogger&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;example_logger&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This creates a custom logger named &lt;code>example_logger&lt;/code>.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Unlike the root logger, the name of a custom logger is not part of the default output format and has to be added to the configuration.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>a custom logger can’t be configured using &lt;code>basicConfig()&lt;/code>. You have to configure it using Handlers and Formatters.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="using-handlers">Using Handlers&lt;/h2>
&lt;p>Handlers are useful when you want to configure your own loggers and send the logs to multiple places when they are generated.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>A logger that you create can have more than one handler $\rightarrow$ you can set it up to be output to a standard output stream and saved to a log file as well.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>You can also set the severity level in handlers&lt;/p>
&lt;ul>
&lt;li>This is useful if you want to set multiple handlers for the same logger but want different severity levels for each of them. E.g., logs with level &lt;code>WARNING&lt;/code> and above to be logged to the console, but everything with level &lt;code>ERROR&lt;/code> and above should also be saved to a file&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h4 id="example">Example&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">logging&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Create a custom logger&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logger&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getLogger&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="vm">__name__&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Create handlers&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">console_handler&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">StreamHandler&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">console_handler&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setLevel&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">WARNING&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">file_handler&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">FileHandler&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;file.log&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">file_handler&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setLevel&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ERROR&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Create formatters and add to handlers&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">date_format&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;%Y-%m-&lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s2"> %H:%M:%S&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">console_format&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Formatter&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">%(asctime)s&lt;/span>&lt;span class="s2"> - &lt;/span>&lt;span class="si">%(name)s&lt;/span>&lt;span class="s2"> - &lt;/span>&lt;span class="si">%(levelname)s&lt;/span>&lt;span class="s2"> - &lt;/span>&lt;span class="si">%(message)s&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">datefmt&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">date_format&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">console_handler&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setFormatter&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">console_format&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">file_format&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Formatter&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">%(asctime)s&lt;/span>&lt;span class="s2"> - &lt;/span>&lt;span class="si">%(name)s&lt;/span>&lt;span class="s2"> - &lt;/span>&lt;span class="si">%(levelname)s&lt;/span>&lt;span class="s2"> - &lt;/span>&lt;span class="si">%(message)s&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">datefmt&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">date_format&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">file_handler&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setFormatter&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">file_format&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Add handlers to the logger&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logger&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">addHandler&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">console_handler&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logger&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">addHandler&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">file_handler&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logger&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">warning&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;This is a warning&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logger&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">error&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;This is an error&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">2023-01-11 14:55:01 - __main__ - WARNING - This is a warning
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">2023-01-11 14:55:01 - __main__ - ERROR - This is an error
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>file.log&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">2023-01-11 14:55:01 - __main__ - ERROR - This is an error
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here, &lt;code>logger.warning()&lt;/code> is creating a &lt;code>LogRecord&lt;/code> that holds all the information of the event and passing it to all the Handlers: &lt;code>console_handler&lt;/code> and &lt;code>file_handler&lt;/code>.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;code>console_handler&lt;/code> is a &lt;code>StreamHandler&lt;/code> with level &lt;code>WARNING&lt;/code> and takes the info from the &lt;code>LogRecord&lt;/code> to generate an output in the format specified and prints it to the console.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>file_handler&lt;/code> is a &lt;code>FileHandler&lt;/code> with level &lt;code>ERROR&lt;/code>, and it ignores this &lt;code>LogRecord&lt;/code> as its level is &lt;code>WARNING&lt;/code>.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>When &lt;code>logger.error()&lt;/code> is called,&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;code>console_handler&lt;/code> behaves exactly as before&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>file_handler&lt;/code> gets a &lt;code>LogRecord&lt;/code> at the level of &lt;code>ERROR&lt;/code>, so it proceeds to generate an output and writes it to the specified file&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>Note: The name of the logger corresponding to the &lt;code>__name__&lt;/code> variable is logged as &lt;code>__main__&lt;/code>, which is the name Python assigns to the module where execution starts. If this file is imported by some other module, then the &lt;code>__name__&lt;/code> variable would correspond to its name &lt;em>logging_example&lt;/em>.&lt;/p>
&lt;h2 id="other-configuration-methods">Other Configuration Methods&lt;/h2>
&lt;p>Except using the module and class functions to configure logging (as above), you can also configure logging by create a &lt;strong>config file&lt;/strong> or a **dictionary **and loading it using &lt;code>fileConfig()&lt;/code> or &lt;code>dictConfig()&lt;/code>, respectively.&lt;/p>
&lt;h3 id="file-configuration">File configuration&lt;/h3>
&lt;p>&lt;code>logging.conf&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-toml" data-lang="toml">&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="nx">loggers&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">keys&lt;/span>&lt;span class="p">=&lt;/span>&lt;span class="nx">root&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nx">sampleLogger&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="nx">handlers&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">keys&lt;/span>&lt;span class="p">=&lt;/span>&lt;span class="nx">consoleHandler&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="nx">formatters&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">keys&lt;/span>&lt;span class="p">=&lt;/span>&lt;span class="nx">sampleFormatter&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="nx">logger_root&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">level&lt;/span>&lt;span class="p">=&lt;/span>&lt;span class="nx">DEBUG&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">handlers&lt;/span>&lt;span class="p">=&lt;/span>&lt;span class="nx">consoleHandler&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="nx">logger_sampleLogger&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">level&lt;/span>&lt;span class="p">=&lt;/span>&lt;span class="nx">DEBUG&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">handlers&lt;/span>&lt;span class="p">=&lt;/span>&lt;span class="nx">consoleHandler&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">qualname&lt;/span>&lt;span class="p">=&lt;/span>&lt;span class="nx">sampleLogger&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">propagate&lt;/span>&lt;span class="p">=&lt;/span>&lt;span class="mi">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="nx">handler_consoleHandler&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">class&lt;/span>&lt;span class="p">=&lt;/span>&lt;span class="nx">StreamHandler&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">level&lt;/span>&lt;span class="p">=&lt;/span>&lt;span class="nx">DEBUG&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">formatter&lt;/span>&lt;span class="p">=&lt;/span>&lt;span class="nx">sampleFormatter&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">args&lt;/span>&lt;span class="p">=&lt;/span>&lt;span class="err">(&lt;/span>&lt;span class="nx">sys&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">stdout&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="err">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="nx">formatter_sampleFormatter&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">format&lt;/span>&lt;span class="p">=&lt;/span>&lt;span class="err">%(&lt;/span>&lt;span class="nx">asctime&lt;/span>&lt;span class="err">)&lt;/span>&lt;span class="nx">s&lt;/span> &lt;span class="nx">-&lt;/span> &lt;span class="err">%(&lt;/span>&lt;span class="nx">name&lt;/span>&lt;span class="err">)&lt;/span>&lt;span class="nx">s&lt;/span> &lt;span class="nx">-&lt;/span> &lt;span class="err">%(&lt;/span>&lt;span class="nx">levelname&lt;/span>&lt;span class="err">)&lt;/span>&lt;span class="nx">s&lt;/span> &lt;span class="nx">-&lt;/span> &lt;span class="err">%(&lt;/span>&lt;span class="nx">message&lt;/span>&lt;span class="err">)&lt;/span>&lt;span class="nx">s&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>
&lt;p>There are two loggers, one handler, and one formatter&lt;/p>
&lt;/li>
&lt;li>
&lt;p>After their names are defined, they are configured by adding the words logger, handler, and formatter before their names separated by an underscore.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>Use &lt;code>fileConfig()&lt;/code> to load this config file&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">logging&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">logging.config&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">pathlib&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Path&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logging_conf_path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Path&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="vm">__file__&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">parent&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">joinpath&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;logging.conf&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">assert&lt;/span> &lt;span class="n">logging_conf_path&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exists&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">config&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">fileConfig&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fname&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">logging_conf_path&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">disable_existing_loggers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">False&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logger&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getLogger&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="vm">__name__&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logger&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">debug&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;This is a debug message.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="dictionary-configuration">Dictionary configuration&lt;/h3>
&lt;p>Same configuration in a &lt;a href="https://realpython.com/python-yaml/">YAML&lt;/a> format for the dictionary approach:&lt;/p>
&lt;p>To configure loggers or handlers, specify attributes as key-values pairs in yaml.&lt;/p>
&lt;p>Example:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">handlers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">console&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">class&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">logging.StreamHandler&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">level&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">DEBUG&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>is equivalent to&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">console_handler&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">StreamHandler&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">console_handler&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setLevel&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DEBUG&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="example-logging_configyaml">Example: &lt;code>logging_config.yaml&lt;/code>&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">formatters&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">simple&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">format&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;%(asctime)s - %(name)s - %(levelname)s - %(message)s&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">handlers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">console&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">class&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">logging.StreamHandler&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">level&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">DEBUG&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">formatter&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">simple&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">stream&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ext://sys.stdout&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">loggers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">sampleLogger&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">level&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">DEBUG&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">handlers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="l">console]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">propagate&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">no&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">root&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">level&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">DEBUG&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">handlers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="l">console]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">logging&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">logging.config&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">yaml&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">pathlib&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Path&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">config_file_path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Path&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="vm">__file__&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">parent&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">joinpath&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;logging_config.yaml&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">assert&lt;/span> &lt;span class="n">config_file_path&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exists&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">with&lt;/span> &lt;span class="nb">open&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">config_file_path&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">config&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">yaml&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">safe_load&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">config&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dictConfig&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">config&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logger&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">logging&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getLogger&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="vm">__name__&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logger&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">debug&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;This is a debug message&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="gotchas">Gotchas&lt;/h2>
&lt;h3 id="setlevel-is-being-ignored">&lt;code>setLevel()&lt;/code> is being ignored&lt;/h3>
&lt;p>In Python &lt;code>logging&lt;/code> package, there are two &lt;code>setLevel()&lt;/code> methods:&lt;/p>
&lt;ul>
&lt;li>The &lt;a href="https://docs.python.org/3/library/logging.html">&lt;code>setLevel()&lt;/code> of &lt;code>Logger&lt;/code>&lt;/a> determines which severity &lt;em>level&lt;/em> of messages it will pass to its handlers. Logging messages which are less severe than &lt;em>level&lt;/em> will be ignored.&lt;/li>
&lt;li>The &lt;code>setLevel()&lt;/code> of &lt;code>Logger&lt;/code> determines which level of messages that handler will send on.&lt;/li>
&lt;/ul>
&lt;p>Reference: &lt;a href="https://stackoverflow.com/questions/64783221/logging-level-is-info-but-only-warnings-are-shown-python-logging">Logging level is info, but only warnings are shown. Python logging - Stack Overflow&lt;/a>&lt;/p>
&lt;h2 id="reference">Reference&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://realpython.com/python-logging/#the-logging-module">Logging in Python – Real Python&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>loguru</title><link>https://haobin-tan.netlify.app/docs/coding/python/useful_packages/loguru/</link><pubDate>Thu, 16 Feb 2023 00:00:00 +0000</pubDate><guid>https://haobin-tan.netlify.app/docs/coding/python/useful_packages/loguru/</guid><description>&lt;p>&lt;img src="https://raw.githubusercontent.com/EckoTan0804/upic-repo/master/uPic/logo.png" alt="GitHub - Delgan/loguru: Python logging made (stupidly) simple">&lt;/p>
&lt;p>&lt;strong>Loguru&lt;/strong> is a library which aims to bring enjoyable logging in Python. It is intended to make Python logging less painful by adding a bunch of useful functionalities that solve caveats of the standard loggers.&lt;/p>
&lt;h2 id="tutorial">Tutorial&lt;/h2>
&lt;p>See: &lt;a href="https://betterstack.com/community/guides/logging/loguru/">A Complete Guide to Logging in Python with Loguru&lt;/a>&lt;/p>
&lt;h2 id="loguru-vs-built-in-logging">&lt;code>loguru&lt;/code> vs. Built-in &lt;code>logging&lt;/code>&lt;/h2>
&lt;p>See&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://alimbekov.com/en/python-logging-vs-loguru/">Python logging HOWTO: logging vs loguru. Python Practice.&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Switch from standard &lt;code>logging&lt;/code> to &lt;code>loguru&lt;/code>:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://loguru.readthedocs.io/en/stable/resources/migration.html">Switching from standard logging to loguru — loguru documentation&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://qxf2.com/blog/replace-python-standard-logging-with-loguru/">Replace Python standard logging mechanism with Loguru&lt;/a>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="issues-and-solutions">Issues and Solutions&lt;/h2>
&lt;h3 id="apply-default-level-color-in-custom-format">Apply default level color in custom format&lt;/h3>
&lt;p>Use the special tag &lt;code>&amp;lt;level&amp;gt;&lt;/code> in custom format.&lt;/p>
&lt;blockquote>
&lt;p>The special tag &lt;code>&amp;lt;level&amp;gt;&lt;/code> (abbreviated with &lt;code>&amp;lt;lvl&amp;gt;&lt;/code>) is transformed according to the configured color of the logged message level.&lt;/p>
&lt;/blockquote>
&lt;p>Reference&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://stackoverflow.com/questions/70977165/how-to-use-loguru-defaults-and-extra-information">python - How to use Loguru defaults + and extra information? - Stack Overflow&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://github.com/Delgan/loguru/issues/122">default message color · Issue #122 · Delgan/loguru · GitHub&lt;/a>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h3 id="integrate-richloggingrichhandler">Integrate &lt;code>rich.logging.RichHandler&lt;/code>&lt;/h3>
&lt;p>Use&lt;a href="https://loguru.readthedocs.io/en/stable/api/logger.html#loguru._logger.Logger.configure"> &lt;code>configure()&lt;/code> method&lt;/a> of &lt;code>loguru.logger&lt;/code>.&lt;/p>
&lt;p>Example:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">rich.logging&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">RichHandler&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">loguru&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">logger&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">rich_handler&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">RichHandler&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logger&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">configure&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">handlers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;sink&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">rich_handler&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;format&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">{message}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="reference">Reference&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://loguru.readthedocs.io/en/stable/index.html">loguru documentation&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://betterstack.com/community/guides/logging/loguru/">A Complete Guide to Logging in Python with Loguru&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://qxf2.com/blog/replace-python-standard-logging-with-loguru/">Replace Python standard logging mechanism with Loguru&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://alimbekov.com/en/python-logging-vs-loguru/">Python logging HOWTO: logging vs loguru. Python Practice.&lt;/a>&lt;/p>
&lt;/li>
&lt;/ul></description></item></channel></rss>