{"id":6181,"date":"2020-07-02T15:13:54","date_gmt":"2020-07-02T13:13:54","guid":{"rendered":"https:\/\/www.codemotion.com\/magazine\/?p=6181"},"modified":"2023-06-19T12:33:13","modified_gmt":"2023-06-19T10:33:13","slug":"logging-in-python-a-broad-gentle-introduction","status":"publish","type":"post","link":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/","title":{"rendered":"Logging in Python: a broad, gentle introduction"},"content":{"rendered":"\t\t\t\t<div class=\"wp-block-uagb-table-of-contents uagb-toc__align-left uagb-toc__columns-1  uagb-block-f9ba9e10      \"\n\t\t\t\t\tdata-scroll= \"1\"\n\t\t\t\t\tdata-offset= \"30\"\n\t\t\t\t\tstyle=\"\"\n\t\t\t\t>\n\t\t\t\t<div class=\"uagb-toc__wrap\">\n\t\t\t\t\t\t<div class=\"uagb-toc__title\">\n\t\t\t\t\t\t\tTable Of Contents\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"uagb-toc__list-wrap \">\n\t\t\t\t\t\t<ol class=\"uagb-toc__list\"><li class=\"uagb-toc__list\"><a href=\"#why-logging\" class=\"uagb-toc-link__trigger\">Why Logging<\/a><li class=\"uagb-toc__list\"><a href=\"#logging-module-intro-and-main-actors\" class=\"uagb-toc-link__trigger\">Logging module: intro and main actors<\/a><li class=\"uagb-toc__list\"><a href=\"#logger-class-methods\" class=\"uagb-toc-link__trigger\">Logger class methods<\/a><li class=\"uagb-toc__list\"><a href=\"#handler-class-method\" class=\"uagb-toc-link__trigger\">Handler class method<\/a><li class=\"uagb-toc__list\"><a href=\"#formatter-class-methods\" class=\"uagb-toc-link__trigger\">Formatter class methods<\/a><li class=\"uagb-toc__list\"><a href=\"#from-theory-and-dummy-examples-to-the-real-word\" class=\"uagb-toc-link__trigger\">From theory and dummy examples to the real word<\/a><li class=\"uagb-toc__list\"><a href=\"#conclusion\" class=\"uagb-toc-link__trigger\">Conclusion<\/a><\/ol>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\n\n\n<p>Not all <a href=\"https:\/\/www.codemotion.com\/magazine\/dev-hub\/big-data-analyst\/a-career-in-data-science\/\">data scientists<\/a> have a <span id=\"urn:enhancement-a4ce248b\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/computer_science\">computer science<\/span> background &#8211; I received my bachelor\u2019s degree in <span id=\"urn:enhancement-31118eae\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/statistics\">Statistics<\/span>, for example. As I moved into <span id=\"urn:enhancement-d8ec1cc8\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span>, I noticed that I was good at <span id=\"urn:enhancement-826849c8\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/scripting_language\">scripting<\/span>, but was not able to create a \u2018production-quality\u2019 code. A fundamental step in writing production-quality code is the ability to log properly. In this article, I will explain how to log in <span id=\"urn:enhancement-79c9ec2f\" class=\"textannotation disambiguated wl-creative-work\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/python_programming_language\">Python<\/span>.<\/p>\n\n\n\n<p>First, we will explore why logging is a fundamental part of any real-world <span id=\"urn:enhancement-ca52a5fe\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/application_software\">application<\/span>. Next, we will look at the main actors in <span id=\"urn:enhancement-aea01e96\" class=\"textannotation disambiguated wl-creative-work\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/python_programming_language\">Python<\/span>\u2019s logging module. Each actor is introduced in both a theoretical and a practical way. We will become familiar with each of these actors by writing simple code examples.<\/p>\n\n\n\n<p>At the end of the article, an example of how to embed the logging library in a structured <span id=\"urn:enhancement-fe4a5dd3\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data\">data<\/span> science project is shown. All the examples used in the article are available in my <a href=\"https:\/\/github.com\/rmenoli\">GitHub repo<\/a>. You can clone this and play with the examples.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-why-logging\">Why Logging<\/h2>\n\n\n\n<p><span id=\"urn:enhancement-9ecbe611\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/logging\">Logging<\/span> is the key to enabling<strong><em> <\/em><\/strong><strong>diagnostic auditing<\/strong>. With a proper <span id=\"urn:enhancement-d54f386c\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/logfile\">log file<\/span>, it\u2019s possible to know what has happened in the <span id=\"urn:enhancement-a0546b7d\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/application_software\">application<\/span>. Has the <span id=\"urn:enhancement-6ab17858\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/application_software\">application<\/span> run smoothly? Has a weird <span id=\"urn:enhancement-96d21287\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/error\">error<\/span> occurred? Does the model perform as expected?<\/p>\n\n\n\n<p>Let\u2019s make these questions more practical by defining an example that we will carry through this article.<\/p>\n\n\n\n<p>We have just developed an <span id=\"urn:enhancement-a10e08\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/application_software\">application<\/span> that makes weather forecasts.<\/p>\n\n\n\n<p>Our <span id=\"urn:enhancement-c2060e0d\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/application_software\">application<\/span> works as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Feature collections: we collect data about air pressure, wind speed, and the presence of clouds in the surrounding area. Each feature has one dedicated sensor and data is transmitted using its <a href=\"https:\/\/www.codemotion.com\/magazine\/dev-hub\/backend-dev\/api-economy-code-api-money\/\">API<\/a>;<\/li>\n\n\n\n<li>Weather forecasts: we select a trained model and use it to predict the weather of the day;<\/li>\n<\/ul>\n\n\n\n<p>The <span id=\"urn:enhancement-a0205b6d\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/project\">project<\/span> is composed of&nbsp; four simple <span id=\"urn:enhancement-178cc9d8\" class=\"textannotation disambiguated wl-creative-work\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/python_programming_language\">Python<\/span> <span id=\"urn:enhancement-bb976559\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/computer_file\">files<\/span>:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">-\n|-&gt; features_ingestion.py\n|-&gt; make_prevision.py\n|-&gt; utils.py\n|-&gt; main.py<\/code><\/span><\/pre>\n\n\n<p>Let\u2019s focus on the features ingestion phase. The <span id=\"urn:enhancement-70e42579\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/scripting_language\">script<\/span> that performs features collection is the following:<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/rmenoli\/8438a541a9b07a2a3b435e9b2a952594.js\" charset=\"utf-8\"><\/script>\n\n\n\n<p>If we launch the <span id=\"urn:enhancement-7791ee6\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/scripting_language\">script<\/span> from the terminal and one of the <span id=\"urn:enhancement-8963cc83\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/application_programming_interface\">APIs<\/span> does not work, we will see the <strong>not easily human-readable<\/strong> standard <span id=\"urn:enhancement-c917988c\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/error_message\">error message<\/span> on the <span id=\"urn:enhancement-ac1c74ee\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/system_console\">console<\/span>.<\/p>\n\n\n\n<p>To make the <span id=\"urn:enhancement-95a775b\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/error\">error<\/span> more readable we can insert a try-except block with a print <span id=\"urn:enhancement-dfdbb125\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/statement_computer_science\">statement<\/span> like the one shown at line 13:<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/rmenoli\/4a8338496879cd6324b8bf503413c7ce.js\" charset=\"utf-8\"><\/script>\n\n\n\n<p>Now we can easily figure out which <span id=\"urn:enhancement-6d35e516\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/application_programming_interface\">API<\/span> is not working\u2026 <strong>if we read the stdout and the stderr on the <span id=\"urn:enhancement-88d21fe9\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/system_console\">console<\/span>!<\/strong><\/p>\n\n\n\n<p>Our boss is very happy with our work. Our weather forecast is so accurate that everyone checks it to decide whether or not go for a hike in the countryside! To improve the <span id=\"urn:enhancement-553d265\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/application_software\">application<\/span>, he has decided to make a forecast every hour &#8211; 24 times a day.<\/p>\n\n\n\n<p>Geat! So, we rent an <span id=\"urn:enhancement-e091f7bb\" class=\"textannotation disambiguated wl-creative-work\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/amazon_web_services\">AWS<\/span> instance, set up the environment and the crontab, and leave the office to go home in a great mood. The next day we arrive at the office at 9 am and\u2026 our boss is yelling! The <span id=\"urn:enhancement-ae77a79\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/application_software\">application<\/span> did not work all night &#8211; it only started to work again a couple of hours ago! Our boss \u2018gently\u2019 asks what happened, and we are unable to answer. <strong>The stderr and stdout were lost when the <span id=\"urn:enhancement-60381321\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/application_software\">application<\/span> finished!<\/strong><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"536\" src=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image1-1024x536.jpg\" alt=\"\" class=\"wp-image-6186\" srcset=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image1-1024x536.jpg 1024w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image1-300x157.jpg 300w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image1-768x402.jpg 768w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image1.jpg 1200w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n<p>To avoid this situation, we have to add <span id=\"urn:enhancement-2c74ae86\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data_logger\">logs<\/span> to our <span id=\"urn:enhancement-41a1367a\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/application_software\">application<\/span>!<\/p>\n\n\n\n<p>A logger is an object that sends messages outside the <span id=\"urn:enhancement-b41d1e55\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/application_software\">application<\/span> for example, in a text <span id=\"urn:enhancement-658bf052\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/computer_file\">file<\/span>. By looking at this text <span id=\"urn:enhancement-3bd67ccb\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/computer_file\">file<\/span> we can find out what happened in our <span id=\"urn:enhancement-d373d1a3\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/application_software\">application<\/span> <strong><em>after<\/em><\/strong><strong> the <span id=\"urn:enhancement-aa94287a\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/application_software\">application<\/span> had finished its run.<\/strong><\/p>\n\n\n\n<p>As a detective, it is important to know <strong>what<\/strong> happened, and both <strong>where<\/strong> and <strong>when<\/strong> it happened. When we write something in the <span id=\"urn:enhancement-c5504ed7\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data_logger\">log<\/span> <span id=\"urn:enhancement-e6a71c3\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/computer_file\">file<\/span>, we must be careful to include all these \u2018<em>w\u2019s\u2019<\/em>. In addition, it is important to provide a <strong>priority scale<\/strong> in the <span id=\"urn:enhancement-12bfe70a\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data_logger\">log<\/span> <span id=\"urn:enhancement-deb7c49f\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/computer_file\">file<\/span> (a <span id=\"urn:enhancement-1fcf66b0\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data_logger\">log<\/span> that notifies us that the <span id=\"urn:enhancement-cfa9179e\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/application_software\">application<\/span> is going to explode should be more visible than a <span id=\"urn:enhancement-327a146d\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data_logger\">log<\/span> that indicates that everything is ok).<\/p>\n\n\n\n<p>The logging priority scale in <span id=\"urn:enhancement-5ea3608d\" class=\"textannotation disambiguated wl-creative-work\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/python_programming_language\">Python<\/span> consists of the following levels:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"293\" src=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image3-1024x293.jpg\" alt=\"Logging levels\" class=\"wp-image-6187\" srcset=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image3-1024x293.jpg 1024w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image3-300x86.jpg 300w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image3-768x220.jpg 768w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image3.jpg 1200w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n<ul class=\"wp-block-list\">\n<li><strong>DEBUG<\/strong>: the messages written in this level provide detailed insights about the application. It is typically used by developers when they find a bug. Have you ever embedded a print statement to check the status of the variables when you have found a bug? If you log a message in the \u2018debug level\u2019 instead, you can avoid having to remove the print statement when your debugging phase is over, and you can reuse the logged message when the next bug appears \ud83d\ude09<\/li>\n\n\n\n<li><strong>INFO<\/strong>: in this level, the messages are used to confirm that the application is running smoothly. We can regard the messages at this level as being the checkpoints of our program.<\/li>\n\n\n\n<li><strong>WARNING<\/strong>: the messages written in this level provide insights that indicate something unusual is going on. The program should be able to handle the problem, but the output could be weird.<\/li>\n\n\n\n<li><strong>ERROR<\/strong>: as suggested by the name, the messages in this level suggest that the application is not working correctly. The output will definitely be affected.<\/li>\n\n\n\n<li><strong>CRITICAL<\/strong>: the highest level. The application will stop running soon and will no longer produce an output.<\/li>\n<\/ul>\n\n\n\n<p>Luckily for us, the logging module in <span id=\"urn:enhancement-1126b8fb\" class=\"textannotation disambiguated wl-creative-work\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/python_programming_language\">Python<\/span> incorporates these properties (the three w\u2019s and the priority levels) with almost no effort.<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-wp-embed is-provider-codemotion-magazine wp-block-embed-codemotion-magazine\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"wp-embedded-content\" data-secret=\"lpKKIdQL2U\"><a href=\"https:\/\/www.codemotion.com\/magazine\/languages\/top-python-frameworks\/\">Top Trending Python Frameworks Today<\/a><\/blockquote><iframe loading=\"lazy\" class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; clip: rect(1px, 1px, 1px, 1px);\" title=\"&#8220;Top Trending Python Frameworks Today&#8221; &#8212; Codemotion Magazine\" src=\"https:\/\/www.codemotion.com\/magazine\/languages\/top-python-frameworks\/embed\/#?secret=YHxoxskTJS#?secret=lpKKIdQL2U\" data-secret=\"lpKKIdQL2U\" width=\"500\" height=\"282\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe>\n<\/div><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-logging-module-intro-and-main-actors\">Logging module: intro and main actors<\/h2>\n\n\n\n<p>The <span id=\"urn:enhancement-1f6c8c11\" class=\"textannotation disambiguated wl-creative-work\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/python_programming_language\">Python<\/span> logging module (<span id=\"urn:enhancement-45204014\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/subroutine\">called<\/span> logging) defines <span id=\"urn:enhancement-77c15beb\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/subroutine\">functions<\/span> and <span id=\"urn:enhancement-6baec0fd\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/class_computer_programming\">classes<\/span> to include structured logs in our <span id=\"urn:enhancement-f7b05365\" class=\"textannotation disambiguated wl-creative-work\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/python_programming_language\">Python<\/span> <span id=\"urn:enhancement-dcb1f43f\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/application_software\">application<\/span>.<\/p>\n\n\n\n<p>The following diagram illustrates the flow of a <span id=\"urn:enhancement-8f82ebaa\" class=\"textannotation disambiguated wl-creative-work\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/python_programming_language\">Python<\/span> program that writes a message into a log <span id=\"urn:enhancement-e92d9838\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/computer_file\">file<\/span>.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"210\" src=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image6-1024x210.png\" alt=\"logging\" class=\"wp-image-6188\" srcset=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image6-1024x210.png 1024w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image6-300x62.png 300w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image6-768x157.png 768w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image6.png 1200w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n<p>As we can see there are three main actors:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>LOGGER<\/strong>: this is the main class of the module. We \u2018interact\u2019 with the logging system through this class of instances. Using its methods, we can write log messages in the log file.<\/li>\n\n\n\n<li><strong>HANDLER<\/strong>: this class determines where the log messages will be written.<\/li>\n\n\n\n<li><strong>FORMATTER<\/strong>: this class is used to decide the format of the log file. With a proper formatter, we can easily add the \u2018three w\u2019s\u2019 to our logger.<\/li>\n<\/ul>\n\n\n\n<p>What follows is a a set of bullet points <span id=\"urn:enhancement-f666da26\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/foreach_loop\">for each<\/span> of the three main <span id=\"urn:enhancement-33a0f33c\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/class_computer_programming\">classes<\/span> that roughly outlines their main <span id=\"urn:enhancement-b73445d\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/method_computer_programming\">methods<\/span> and initialization <span id=\"urn:enhancement-852c394c\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/subroutine\">functions<\/span>. Don\u2019t worry if you don\u2019t understand the functionality of the <span id=\"urn:enhancement-d6449a83\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/method_computer_programming\">methods<\/span> &#8211; the examples below will make these clearer.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-logger-class-methods\">Logger class methods<\/h2>\n\n\n\n<p>To get an <span id=\"urn:enhancement-be71faee\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/instance_computer_science\">instance<\/span> of the Logger <span id=\"urn:enhancement-f3fef1cb\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/class_computer_programming\">class<\/span> we have to call the <span id=\"urn:enhancement-a4d6eae0\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/subroutine\">function<\/span> <code>getLogger(logger_name)<\/code>.<\/p>\n\n\n\n<p>Once we have a Logger <span id=\"urn:enhancement-5855ef68\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/instance_computer_science\">instance<\/span> we can call the main <span id=\"urn:enhancement-5216f336\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/method_computer_programming\">methods<\/span>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>debug(message)<\/code>: to log a message at the debug level<\/li>\n\n\n\n<li><code>info(message)<\/code>: to log a message at the info level<\/li>\n\n\n\n<li><code>warning(message)<\/code>: to log a message at the warning level<\/li>\n\n\n\n<li><code>critical(message)<\/code>: to log a message at the error level<\/li>\n\n\n\n<li><code>addHandler(handlerObj)<\/code>: to add an handler object<\/li>\n\n\n\n<li><code>setLevel(logging_level)<\/code>: to set the level <em>from which <\/em>the logger starts to log.<\/li>\n<\/ul>\n\n\n\n<p>For a&nbsp; more practical example, let\u2019s create the first <span id=\"urn:enhancement-6af2e6af\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/scripting_language\">script<\/span> to embed the <span id=\"urn:enhancement-9e5c98f2\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data_logger\">logging<\/span> module:<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/rmenoli\/7894ba59c4b6451d022d0d893165d066.js\" charset=\"utf-8\"><\/script>\n\n\n\n<p>If we run the <span id=\"urn:enhancement-785e8096\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/scripting_language\">script<\/span>, the output<em> on the console<\/em> will be:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">Something critical\nAn error\nA warning<\/code><\/span><\/pre>\n\n\n<p>Only messages with a level equal to or higher than \u2018warning\u2019 are output! This happens because the<strong> default configuration<\/strong> of the <span id=\"urn:enhancement-516f63ab\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data_logger\">logging<\/span> module is the warning level. To output all the <span id=\"urn:enhancement-c8e8fac9\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/message_passing\">messages<\/span>, we have to use the <code>setLevel<em>(<span id=\"urn:enhancement-3b31024e\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data_logger\">logging<\/span>_level)<\/em><\/code><em> <span id=\"urn:enhancement-70ba0f8a\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/method_computer_programming\"><\/em>method<\/span>.<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/rmenoli\/f5c1b1b76f029c501cf6fbfdd3be1936.js\" charset=\"utf-8\"><\/script>\n\n\n\n<p>The output on the <span id=\"urn:enhancement-c14a1a71\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/system_console\">console<\/span> is now:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">Something critical\nAn error\nA warning\nMy info is that you are here\nI'm debugging<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id=\"h-handler-class-method\">Handler class method<\/h2>\n\n\n\n<p>The <span id=\"urn:enhancement-24af9c03\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/subroutine\">function<\/span> to <span id=\"urn:enhancement-ded83f0d\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/subroutine\">call<\/span> to instantiate an handler object depends on the output source that we want to use (I know this title is not 100% correct &#8211; we have several handlers, but I think it is better to imagine the handler as a \u2018unique\u2019 object that sends <span id=\"urn:enhancement-c1d6ee1b\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/message_passing\">messages<\/span> to the desired stream). The most commonly used <span id=\"urn:enhancement-6592d529\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/subroutine\">functions<\/span> to instantiate an handler object are the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>StreamHandler()<\/code>: to instantiate a Handler that sends messages <strong>to stdout and stderr.<\/strong><\/li>\n\n\n\n<li><code>StreamHandler(file_path)<\/code>: to instantiate a Handler that sends messages to a <strong>text file<\/strong>. (There are many varieties of FileHandler such as <code>RotatingFileHandler<\/code> and <code>TimeRotatingFileHandler<\/code>)<\/li>\n<\/ul>\n\n\n\n<p>However, we can instantiate handlers to send emails or to send <span id=\"urn:enhancement-2271e2fe\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/message_passing\">messages<\/span> through <span id=\"urn:enhancement-fc83731c\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/transmission_control_protocol\">TCP<\/span>\/<span id=\"urn:enhancement-f0c2de14\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/internet_protocol\">IP<\/span> <span id=\"urn:enhancement-b544bad7\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/network_socket\">sockets<\/span> or <span id=\"urn:enhancement-f2564fb6\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/hypertext_transfer_protocol\">HTTP<\/span> <span id=\"urn:enhancement-7f4fd174\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/server_computing\">servers<\/span>!<\/p>\n\n\n\n<p>Check the logging.handlers module <a href=\"https:\/\/docs.python.org\/3\/library\/logging.handlers.html\">documentation<\/a> for more info!<\/p>\n\n\n\n<p>The main methods of a handler are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>setFormatter(formatter)<\/code>: to determine the formatter of the handler.<\/li>\n\n\n\n<li><code>setLevel(logging_level)<\/code>: to set the level <em>from which <\/em>the handler starts to log.<br><strong>NOTE<\/strong> that the level of the handler should be <em>higher than or equal to <\/em>the level of its logger.<\/li>\n<\/ul>\n\n\n\n<p>Let\u2019s get our hands dirty by adding a Handler to our previous example.We\u2019ll <span id=\"urn:enhancement-8a2577e7\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data_logger\">log<\/span> in a <span id=\"urn:enhancement-3337d9a0\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/computer_file\">file<\/span> named <em>logfile.log<\/em>.<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/rmenoli\/45d9509f27f49b8cf5c6b9c675dd12ac.js\" charset=\"utf-8\"><\/script>\n\n\n\n<p>Now we have an empty console. All the <span id=\"urn:enhancement-584df223\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/message_passing\">messages<\/span> are in the following <span id=\"urn:enhancement-d278c6b3\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/computer_file\">file<\/span>:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image2.png\" alt=\"log file\" class=\"wp-image-6190\" width=\"574\" height=\"267\" srcset=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image2.png 734w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image2-300x140.png 300w\" sizes=\"auto, (max-width: 574px) 100vw, 574px\" \/><\/figure><\/div>\n\n\n<p>Let\u2019s make things a bit more amusing.<\/p>\n\n\n\n<p>We can <span id=\"urn:enhancement-ec94678a\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data_logger\">log<\/span> <strong>with the same logger both on the console and in the <span id=\"urn:enhancement-3509318b\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data_logger\">log<\/span> <span id=\"urn:enhancement-96a06db0\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/computer_file\">file<\/span>. <\/strong>On the console we will <span id=\"urn:enhancement-2b6b9d9f\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data_logger\">log<\/span> all the levels (we would like to see our whole \u201cprint\u201d), but in the <span id=\"urn:enhancement-ed5cb893\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/computer_file\">file<\/span> we will <span id=\"urn:enhancement-19f74b3c\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/data_logger\">log<\/span> from the warning level, so that we track (and keep) only records regarding the problems that actually occurred.<\/p>\n\n\n\n<p>The code to perform this task is:<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/rmenoli\/323dcf85951d318b15196af80f278553.js\" charset=\"utf-8\"><\/script>\n\n\n\n<p>The output is presented in this funny gif \ud83d\ude09<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"400\" src=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image4.gif\" alt=\"\" class=\"wp-image-6191\"\/><\/figure><\/div>\n\n\n<p>With a simple line we are able to log in two different places with two different levels! How cool is that!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-formatter-class-methods\">Formatter class methods<\/h2>\n\n\n\n<p>To get an <span id=\"urn:enhancement-a8fff512\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/instance_computer_science\">instance<\/span> of the Formatter <span id=\"urn:enhancement-a832296d\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/class_computer_programming\">class<\/span> we have to call the module\u2019s function <em>Formatter()<\/em>. This <span id=\"urn:enhancement-d6a41762\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/class_computer_programming\">class<\/span> does not have <span id=\"urn:enhancement-fcddb102\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/method_computer_programming\">methods<\/span>. The Formatter <span id=\"urn:enhancement-82b70163\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/constructor_object-oriented_programming\">constructor function<\/span> takes as input three optional arguments: a <span id=\"urn:enhancement-38f19370\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/message_format\">message format<\/span> string, a date format string, and a style indicator. The core argument is the <span id=\"urn:enhancement-ffa64e84\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/message_format\">message format<\/span> string &#8211; let\u2019s focus on that. <strong>The <span id=\"urn:enhancement-4fcb8e9\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/message_format\">message format<\/span> string defines the structure of all the <span id=\"urn:enhancement-35d4b586\" class=\"textannotation disambiguated wl-thing\" itemid=\"http:\/\/data.wordlift.io\/wl01770\/entity\/message_passing\">messages<\/span> that will be written<\/strong>. The message format string is composed of <em>LogRecord attributes<\/em>: you can see the list of LogRecord attributes <a href=\"https:\/\/docs.python.org\/3\/library\/logging.html#logrecord-attributes\" target=\"_blank\" aria-label=\"undefined (opens in a new tab)\" rel=\"noreferrer noopener nofollow\">here<\/a>. The key attributes are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><em>levelname<\/em>: the log level of the input message<\/li>\n\n\n\n<li><em>message<\/em>: the log message itself.<\/li>\n\n\n\n<li><em>asctime<\/em>: time at which the log method is created<\/li>\n\n\n\n<li><em>module<\/em>: the name of the module that contains the message.<\/li>\n\n\n\n<li><em>funcName<\/em>: the name of the function that contains the message.<\/li>\n\n\n\n<li><em>args<\/em>: list of arguments used to call the associated function or method.<\/li>\n<\/ul>\n\n\n\n<p>With the former list we are able to <strong>programmatically write the \u2018three w\u2019s\u2019<\/strong> <strong>and the priority scale<\/strong><strong><em> <\/em><\/strong><strong>in our log messages<\/strong>. With the level name we write the priority scale. With the <em>message LogRecord<\/em> <em>attribute<\/em>, we answer the \u2018<em>what?<\/em>\u2019 question. With the <em>asctime<\/em> <em>LogRecord<\/em> <em>attribute<\/em> we will define the \u201c<em>when<\/em>\u201d. With the remaining LogRecord attributes we define the \u201c<em>where<\/em>\u201d.<\/p>\n\n\n\n<p>Let\u2019s add a formatter to our handlers:<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/rmenoli\/33bde3b5bd50ed4c1ec6d0936809e9af.js\" charset=\"utf-8\"><\/script>\n\n\n\n<p>Now the output on the console is:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-number\">2020<\/span><span class=\"hljs-number\">-06<\/span><span class=\"hljs-number\">-09<\/span> <span class=\"hljs-number\">21<\/span>:<span class=\"hljs-number\">48<\/span>:<span class=\"hljs-number\">07<\/span>,<span class=\"hljs-number\">825<\/span>~CRITICAL~Something critical~<span class=\"hljs-built_in\">module<\/span>:log_hand_log_1\n<span class=\"hljs-number\">2020<\/span><span class=\"hljs-number\">-06<\/span><span class=\"hljs-number\">-09<\/span> <span class=\"hljs-number\">21<\/span>:<span class=\"hljs-number\">48<\/span>:<span class=\"hljs-number\">07<\/span>,<span class=\"hljs-number\">825<\/span>~ERROR~An error~<span class=\"hljs-built_in\">module<\/span>:log_hand_log_1\n<span class=\"hljs-number\">2020<\/span><span class=\"hljs-number\">-06<\/span><span class=\"hljs-number\">-09<\/span> <span class=\"hljs-number\">21<\/span>:<span class=\"hljs-number\">48<\/span>:<span class=\"hljs-number\">07<\/span>,<span class=\"hljs-number\">825<\/span>~WARNING~A warning~<span class=\"hljs-built_in\">module<\/span>:log_hand_log_1\n<span class=\"hljs-number\">2020<\/span><span class=\"hljs-number\">-06<\/span><span class=\"hljs-number\">-09<\/span> <span class=\"hljs-number\">21<\/span>:<span class=\"hljs-number\">48<\/span>:<span class=\"hljs-number\">07<\/span>,<span class=\"hljs-number\">826<\/span>~INFO~My info is that you are here~<span class=\"hljs-built_in\">module<\/span>:log_hand_log_1\n<span class=\"hljs-number\">2020<\/span><span class=\"hljs-number\">-06<\/span><span class=\"hljs-number\">-09<\/span> <span class=\"hljs-number\">21<\/span>:<span class=\"hljs-number\">48<\/span>:<span class=\"hljs-number\">07<\/span>,<span class=\"hljs-number\">826<\/span>~DEBUG~I<span class=\"hljs-string\">'m debugging~module:log_hand_log_1<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Can you see the power of the logger? We did not change the messages in lines 17\u201321, but we have decorated them with the timestamp, the level, and the module where the messages were generated. These insights cost nothing!<\/p>\n\n\n\n<p>We can also provide different formatters for different handlers of the same logger. In this way, we can have a \u2018cleaner\u2019 output on the console and a \u2018detailed\u2019 output in the log file.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-from-theory-and-dummy-examples-to-the-real-word\">From theory and dummy examples to the real word<\/h2>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"495\" height=\"350\" src=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image5.png\" alt=\"\" class=\"wp-image-6192\" srcset=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image5.png 495w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image5-300x212.png 300w, https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/image5-180x128.png 180w\" sizes=\"auto, (max-width: 495px) 100vw, 495px\" \/><\/figure><\/div>\n\n\n<p>Now that we have the power of logging at our fingertips we have to use it to make our boss happy. Let\u2019s return to our weather forecast example and embed the logging module in the application.<\/p>\n\n\n\n<p>Impulsively, we will add the logger to the script that is most likely to raise an exception: the \u2018famous\u2019 ingestion script. Without thinking too much, we will cut and paste from the code of the tutorial above. The result is the following code:<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/rmenoli\/02d6f688da0e1a0cadda0681337ba3f8.js\" charset=\"utf-8\"><\/script>\n\n\n\n<p>We instantiated the logger within the lines 5\u201318 (too many lines!).<\/p>\n\n\n\n<p>We log messages in lines 21, 29, 33 and 38.<\/p>\n\n\n\n<p>Now, if an API does not work, the program will write a record like this in the logfile.log:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">2020-06-10 00:20:28,899~CRITICAL~API <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">class<\/span> '<span class=\"hljs-attr\">utils.AirPressureApi<\/span>'&gt;<\/span> did not work~module:ingestion_weather~module:feature_ingestion<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Thus, when we arrive at the office in the morning we can easily see that at twenty minutes past midnight the ingestion script experienced an error caused by the Air Pressure API.<\/p>\n\n\n\n<p>But&#8230; what if we want to embed the logging module in our application\u2019s other scripts as well?<\/p>\n\n\n\n<p>Let\u2019s quickly recall the structure of the application:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">-\n|-&gt; features_ingestion.py\n|-&gt; make_prevision.py\n|-&gt; utils.py\n|-&gt; main.py<\/code><\/span><\/pre>\n\n\n<p><em>main.py<\/em> will call <em>features_ingestion.py <\/em>or <em>make_prevision.py<\/em><\/p>\n\n\n\n<p>In order to write a in a <strong>unique log file for all the logs <\/strong>from the two scripts<strong>, <\/strong>we have two options:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Instantiate a unique logger object in <em>main.py<\/em> and pass it to the other scripts.<\/li>\n\n\n\n<li>Instantiate many logger objects with the same handler and the same formatter. Each logger object will therefore send the output of its module to the same location, with the same format.<\/li>\n<\/ol>\n\n\n\n<p>Python\u2019s convention is to create a logger instance for each module. The name of each logger is the name of the module. In order to keep the settings (handler, levels, formatters) the same, creating a \u2018logger factory\u2019 module is recommended, like this:<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/rmenoli\/a23b42da4fff74d15fd8aaf79c69a9a0.js\" charset=\"utf-8\"><\/script>\n\n\n\n<p>With the creation of the logger factory module, our application is now structured as follows:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">-\n|-&gt; features_ingestion.py\n|-&gt; make_prevision.py\n|-&gt; utils.py\n|-&gt; main.py\n|-&gt; mylogger.py<\/code><\/span><\/pre>\n\n\n<p>Now, the ingestion script will be:<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/rmenoli\/2697b8d5532cdd2ffd3b95ca2dc2fdfe.js\" charset=\"utf-8\"><\/script>\n\n\n\n<p>and the <em>make_prevision.py<\/em> will be:<\/p>\n\n\n\n<script src=\"https:\/\/gist.github.com\/rmenoli\/7fd040e0e6090fd7c11dfaabf8aaacc7.js\" charset=\"utf-8\"><\/script>\n\n\n\n<p>If an error occurs in the ingestion phase at midnight, and another error occurs in the make_prevision script at one a.m., the next morning we will find the following logfile:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">2020-06-10 00:00:00,899~CRITICAL~API <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">class<\/span> '<span class=\"hljs-attr\">utils.HumidityApi<\/span>'&gt;<\/span> did not work~module:ingestion_weather~module:feature_ingestion\n2020-06-10 01:00:00,899~CRITICAL~Problem in loading~module:make_prevision<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id=\"h-conclusion\">Conclusion<\/h2>\n\n\n\n<p>In this tutorial we have seen why logging is a key element when we have to put our code into production. We have seen the main actors of the <a href=\"https:\/\/www.codemotion.com\/magazine\/python\" target=\"_blank\" rel=\"noreferrer noopener\">Python <\/a>logging module; we started by creating dummy examples to get our hands dirty, and by the end, the logging module was embedded in a little \u2018real-word\u2019 application.<\/p>\n\n\n\n<p>All developers make errors and all programs crash. <a href=\"https:\/\/www.codemotion.com\/magazine\/dev-hub\/backend-dev\/5-habits-of-highly-successful-developers\/\">Highly successful developers<\/a> have the ability to quickly identify and solve the problem. The logging module is one of the most powerful tools at our disposal to easily identify the source of any problem.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Not all data scientists have a computer science background &#8211; I received my bachelor\u2019s degree in Statistics, for example. As I moved into data, I noticed that I was good at scripting, but was not able to create a \u2018production-quality\u2019 code. A fundamental step in writing production-quality code is the ability to log properly. In&#8230; <a class=\"more-link\" href=\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/\">Read more<\/a><\/p>\n","protected":false},"author":104,"featured_media":6182,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_editorskit_title_hidden":false,"_editorskit_reading_time":9,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","_uag_custom_page_level_css":"","_genesis_hide_title":false,"_genesis_hide_breadcrumbs":false,"_genesis_hide_singular_image":false,"_genesis_hide_footer_widgets":false,"_genesis_custom_body_class":"","_genesis_custom_post_class":"","_genesis_layout":"","footnotes":""},"categories":[16],"tags":[4446,68],"collections":[],"class_list":{"0":"post-6181","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-big-data","8":"tag-data-analysis","9":"tag-python","10":"entry"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.9 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Logging in Python: a broad, gentle introduction - Codemotion Magazine<\/title>\n<meta name=\"description\" content=\"A fundamental step in writing production-quality code is the ability to log properly. In this article, I will explain how to log in Python.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Logging in Python: a broad, gentle introduction\" \/>\n<meta property=\"og:description\" content=\"A fundamental step in writing production-quality code is the ability to log properly. In this article, I will explain how to log in Python.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/\" \/>\n<meta property=\"og:site_name\" content=\"Codemotion Magazine\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Codemotion.Italy\/\" \/>\n<meta property=\"article:published_time\" content=\"2020-07-02T13:13:54+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-06-19T10:33:13+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"969\" \/>\n\t<meta property=\"og:image:height\" content=\"675\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Riccardo Menoli\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@CodemotionIT\" \/>\n<meta name=\"twitter:site\" content=\"@CodemotionIT\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Riccardo Menoli\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/\"},\"author\":{\"name\":\"Riccardo Menoli\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#\/schema\/person\/0b2257f70957a8230d487daa953ec6a9\"},\"headline\":\"Logging in Python: a broad, gentle introduction\",\"datePublished\":\"2020-07-02T13:13:54+00:00\",\"dateModified\":\"2023-06-19T10:33:13+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/\"},\"wordCount\":2268,\"publisher\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled.jpg\",\"keywords\":[\"Data Analysis\",\"Python\"],\"articleSection\":[\"Big Data\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/\",\"url\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/\",\"name\":\"Logging in Python: a broad, gentle introduction - Codemotion Magazine\",\"isPartOf\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled.jpg\",\"datePublished\":\"2020-07-02T13:13:54+00:00\",\"dateModified\":\"2023-06-19T10:33:13+00:00\",\"description\":\"A fundamental step in writing production-quality code is the ability to log properly. In this article, I will explain how to log in Python.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/#primaryimage\",\"url\":\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled.jpg\",\"contentUrl\":\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled.jpg\",\"width\":969,\"height\":675,\"caption\":\"logging python\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.codemotion.com\/magazine\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"AI\/ML\",\"item\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Big Data\",\"item\":\"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Logging in Python: a broad, gentle introduction\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#website\",\"url\":\"https:\/\/www.codemotion.com\/magazine\/\",\"name\":\"Codemotion Magazine\",\"description\":\"We code the future. Together\",\"publisher\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.codemotion.com\/magazine\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#organization\",\"name\":\"Codemotion\",\"url\":\"https:\/\/www.codemotion.com\/magazine\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2019\/11\/codemotionlogo.png\",\"contentUrl\":\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2019\/11\/codemotionlogo.png\",\"width\":225,\"height\":225,\"caption\":\"Codemotion\"},\"image\":{\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/Codemotion.Italy\/\",\"https:\/\/x.com\/CodemotionIT\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#\/schema\/person\/0b2257f70957a8230d487daa953ec6a9\",\"name\":\"Riccardo Menoli\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.codemotion.com\/magazine\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/8804d0bb4c445d0b2be47ff09ee5ec5d551c324da6090e77e5c506b147281bcb?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/8804d0bb4c445d0b2be47ff09ee5ec5d551c324da6090e77e5c506b147281bcb?s=96&d=mm&r=g\",\"caption\":\"Riccardo Menoli\"},\"url\":\"https:\/\/www.codemotion.com\/magazine\/author\/riccardo-menoli\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Logging in Python: a broad, gentle introduction - Codemotion Magazine","description":"A fundamental step in writing production-quality code is the ability to log properly. In this article, I will explain how to log in Python.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/","og_locale":"en_US","og_type":"article","og_title":"Logging in Python: a broad, gentle introduction","og_description":"A fundamental step in writing production-quality code is the ability to log properly. In this article, I will explain how to log in Python.","og_url":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/","og_site_name":"Codemotion Magazine","article_publisher":"https:\/\/www.facebook.com\/Codemotion.Italy\/","article_published_time":"2020-07-02T13:13:54+00:00","article_modified_time":"2023-06-19T10:33:13+00:00","og_image":[{"width":969,"height":675,"url":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled.jpg","type":"image\/jpeg"}],"author":"Riccardo Menoli","twitter_card":"summary_large_image","twitter_creator":"@CodemotionIT","twitter_site":"@CodemotionIT","twitter_misc":{"Written by":"Riccardo Menoli","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/#article","isPartOf":{"@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/"},"author":{"name":"Riccardo Menoli","@id":"https:\/\/www.codemotion.com\/magazine\/#\/schema\/person\/0b2257f70957a8230d487daa953ec6a9"},"headline":"Logging in Python: a broad, gentle introduction","datePublished":"2020-07-02T13:13:54+00:00","dateModified":"2023-06-19T10:33:13+00:00","mainEntityOfPage":{"@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/"},"wordCount":2268,"publisher":{"@id":"https:\/\/www.codemotion.com\/magazine\/#organization"},"image":{"@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/#primaryimage"},"thumbnailUrl":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled.jpg","keywords":["Data Analysis","Python"],"articleSection":["Big Data"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/","url":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/","name":"Logging in Python: a broad, gentle introduction - Codemotion Magazine","isPartOf":{"@id":"https:\/\/www.codemotion.com\/magazine\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/#primaryimage"},"image":{"@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/#primaryimage"},"thumbnailUrl":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled.jpg","datePublished":"2020-07-02T13:13:54+00:00","dateModified":"2023-06-19T10:33:13+00:00","description":"A fundamental step in writing production-quality code is the ability to log properly. In this article, I will explain how to log in Python.","breadcrumb":{"@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/#primaryimage","url":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled.jpg","contentUrl":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled.jpg","width":969,"height":675,"caption":"logging python"},{"@type":"BreadcrumbList","@id":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/logging-in-python-a-broad-gentle-introduction\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.codemotion.com\/magazine\/"},{"@type":"ListItem","position":2,"name":"AI\/ML","item":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/"},{"@type":"ListItem","position":3,"name":"Big Data","item":"https:\/\/www.codemotion.com\/magazine\/ai-ml\/big-data\/"},{"@type":"ListItem","position":4,"name":"Logging in Python: a broad, gentle introduction"}]},{"@type":"WebSite","@id":"https:\/\/www.codemotion.com\/magazine\/#website","url":"https:\/\/www.codemotion.com\/magazine\/","name":"Codemotion Magazine","description":"We code the future. Together","publisher":{"@id":"https:\/\/www.codemotion.com\/magazine\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.codemotion.com\/magazine\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.codemotion.com\/magazine\/#organization","name":"Codemotion","url":"https:\/\/www.codemotion.com\/magazine\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.codemotion.com\/magazine\/#\/schema\/logo\/image\/","url":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2019\/11\/codemotionlogo.png","contentUrl":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2019\/11\/codemotionlogo.png","width":225,"height":225,"caption":"Codemotion"},"image":{"@id":"https:\/\/www.codemotion.com\/magazine\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/Codemotion.Italy\/","https:\/\/x.com\/CodemotionIT"]},{"@type":"Person","@id":"https:\/\/www.codemotion.com\/magazine\/#\/schema\/person\/0b2257f70957a8230d487daa953ec6a9","name":"Riccardo Menoli","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.codemotion.com\/magazine\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/8804d0bb4c445d0b2be47ff09ee5ec5d551c324da6090e77e5c506b147281bcb?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/8804d0bb4c445d0b2be47ff09ee5ec5d551c324da6090e77e5c506b147281bcb?s=96&d=mm&r=g","caption":"Riccardo Menoli"},"url":"https:\/\/www.codemotion.com\/magazine\/author\/riccardo-menoli\/"}]}},"featured_image_src":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled-600x400.jpg","featured_image_src_square":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled-600x600.jpg","author_info":{"display_name":"Riccardo Menoli","author_link":"https:\/\/www.codemotion.com\/magazine\/author\/riccardo-menoli\/"},"uagb_featured_image_src":{"full":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled.jpg",969,675,false],"thumbnail":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled-150x150.jpg",150,150,true],"medium":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled-300x209.jpg",300,209,true],"medium_large":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled-768x535.jpg",768,535,true],"large":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled.jpg",969,675,false],"1536x1536":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled.jpg",969,675,false],"2048x2048":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled.jpg",969,675,false],"small-home-featured":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled.jpg",100,70,false],"sidebar-featured":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled-180x128.jpg",180,128,true],"genesis-singular-images":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled-896x504.jpg",896,504,true],"archive-featured":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled-400x225.jpg",400,225,true],"gb-block-post-grid-landscape":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled-600x400.jpg",600,400,true],"gb-block-post-grid-square":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2020\/07\/logging-scaled-600x600.jpg",600,600,true]},"uagb_author_info":{"display_name":"Riccardo Menoli","author_link":"https:\/\/www.codemotion.com\/magazine\/author\/riccardo-menoli\/"},"uagb_comment_info":0,"uagb_excerpt":"Not all data scientists have a computer science background &#8211; I received my bachelor\u2019s degree in Statistics, for example. As I moved into data, I noticed that I was good at scripting, but was not able to create a \u2018production-quality\u2019 code. A fundamental step in writing production-quality code is the ability to log properly. In&#8230;&hellip;","lang":"en","_links":{"self":[{"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/posts\/6181","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/users\/104"}],"replies":[{"embeddable":true,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/comments?post=6181"}],"version-history":[{"count":8,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/posts\/6181\/revisions"}],"predecessor-version":[{"id":21453,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/posts\/6181\/revisions\/21453"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/media\/6182"}],"wp:attachment":[{"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/media?parent=6181"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/categories?post=6181"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/tags?post=6181"},{"taxonomy":"collections","embeddable":true,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/collections?post=6181"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}