<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alwoch Sophia</title>
    <description>The latest articles on DEV Community by Alwoch Sophia (@alwoch).</description>
    <link>https://dev.to/alwoch</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F874613%2Fd4cd7823-fe04-4350-8142-fa8fd43ae448.png</url>
      <title>DEV Community: Alwoch Sophia</title>
      <link>https://dev.to/alwoch</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alwoch"/>
    <language>en</language>
    <item>
      <title>Understanding the impact of Python variable assignment technique using the Fibonacci sequence</title>
      <dc:creator>Alwoch Sophia</dc:creator>
      <pubDate>Fri, 26 May 2023 07:59:40 +0000</pubDate>
      <link>https://dev.to/alwoch/understanding-the-impact-of-python-variable-assignment-technique-using-the-fibonacci-sequence-3pk7</link>
      <guid>https://dev.to/alwoch/understanding-the-impact-of-python-variable-assignment-technique-using-the-fibonacci-sequence-3pk7</guid>
      <description>&lt;p&gt;Python offers two ways to assign variables; single and multiple variable assignment. The choice of which variable assignment technique you use sometimes has a tremendous effect on your code's accuracy.&lt;/p&gt;

&lt;p&gt;This article will explain the two variable assignment methods and will use the &lt;a href="https://en.wikipedia.org/wiki/Fibonacci_sequence"&gt;Fibonacci sequence&lt;/a&gt; to illustrate the variation in results caused by each of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow along, you should have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A code editor such as &lt;a href="https://code.visualstudio.com/"&gt;VScode&lt;/a&gt; installed on your computer or online IDE such as &lt;a href="https://replit.com/"&gt;replit&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Python installed if you're using a code editor locally on your machine.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  single variable assignment
&lt;/h2&gt;

&lt;p&gt;Under single variable assignment, only a single value is assigned to a single variable as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x=5

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If under the first &lt;code&gt;x&lt;/code&gt; variable assignment, you reinitialised &lt;code&gt;x&lt;/code&gt; with the value &lt;code&gt;10&lt;/code&gt; and printed it, the previous value would be overwritten and you'd have &lt;code&gt;10&lt;/code&gt; as the new value of &lt;code&gt;x&lt;/code&gt; as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--msBEbsGG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1685024258257/302ca5a0-e741-4c7d-98b3-a5feb5ce989c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--msBEbsGG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1685024258257/302ca5a0-e741-4c7d-98b3-a5feb5ce989c.png" alt="variable reassignment" width="763" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  multiple variable assignment
&lt;/h2&gt;

&lt;p&gt;Under multiple variable assignment, multiple variables can reference a single value as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_KiB6Dds--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1685025201831/6910d860-f303-4944-8f4f-c8cdc7747671.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_KiB6Dds--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1685025201831/6910d860-f303-4944-8f4f-c8cdc7747671.png" alt="" width="763" height="181"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;variable assignment in Python follows the right-to-left rule and what happens in this case is that the value &lt;code&gt;10&lt;/code&gt; is first assigned to the variable &lt;code&gt;r&lt;/code&gt;, then &lt;code&gt;r&lt;/code&gt; assigned to &lt;code&gt;q&lt;/code&gt; and finally, &lt;code&gt;q&lt;/code&gt; gets assigned to &lt;code&gt;p&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Also under multiple variable assignment, multiple values can be assigned to multiple variables on a single line as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wQpdUt6I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1685025684222/6eb9cfdf-8080-4d8b-8202-5bb6b80d565a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wQpdUt6I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1685025684222/6eb9cfdf-8080-4d8b-8202-5bb6b80d565a.png" alt="" width="763" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above example, a tuple of &lt;code&gt;(5,10,15)&lt;/code&gt; is created and iterated over to assign the values to &lt;code&gt;a,b&lt;/code&gt; and &lt;code&gt;c&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now you must be thinking &lt;em&gt;"Oh I could just choose the single variable assignment and stick with it"&lt;/em&gt; -but sometimes it's not &lt;em&gt;one size fits all&lt;/em&gt;. Depending on the problem, a change in variable assignment may be required to attain the desired level of accuracy.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fibonacci Sequence
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;In mathematics, the &lt;strong&gt;Fibonacci Sequence&lt;/strong&gt; is a &lt;a href="https://en.wikipedia.org/wiki/Integer_sequence"&gt;sequence&lt;/a&gt; in which each number is the sum of the two preceding ones. Numbers that are part of the Fibonacci sequence are known as &lt;strong&gt;Fibonacci numbers.&lt;/strong&gt; The sequence commonly starts from 0 and 1, although some authors start the sequence from 1 and 1 or sometimes (as did Fibonacci) from 1 and 2. Starting from 0 and 1, the first few values in the sequence are:&lt;/p&gt;

&lt;p&gt;0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Wikipedia&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;To break it down, there are two initial numbers in the sequence; &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt;. The next Fibonacci number is the sum of &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt; which is &lt;code&gt;1&lt;/code&gt;. The sequence now consists of &lt;code&gt;0,1,1.&lt;/code&gt; The next number would be a sum of the last two numbers in the sequence - &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt; to make it &lt;code&gt;0,1,1,2&lt;/code&gt; and so on....&lt;/p&gt;

&lt;p&gt;In this example, the goal is to write a function with a parameter &lt;code&gt;n&lt;/code&gt; -that will generate Fibonacci numbers using &lt;code&gt;n&lt;/code&gt; as the limit. The steps to achieve this are broken down as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;create variables &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; to store the initial values &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt; respectively&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;create an empty array for the Fibonacci numbers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;loop through the limit to add the Fibonacci numbers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;in the loop, set &lt;code&gt;x&lt;/code&gt; to the value &lt;code&gt;y&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; to the sum of &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;return the array of Fibonacci numbers&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The above pseudo-code now becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def generate_fibonacci(n):
  x= 0
  y=1
  fibs = []
  while x &amp;lt; n:
    fibs.append(x)
    x = y
    y = x + y
  return fibs

print(generate_fibonacci(100))

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you run this code, you should have the following result in your terminal&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zqoLnI6e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1685034908812/d65a12d8-beac-4d5c-bd23-874e0c0324ed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zqoLnI6e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1685034908812/d65a12d8-beac-4d5c-bd23-874e0c0324ed.png" alt="" width="761" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just to be sure the function is returning accurate results, add a unit test to test its output&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import unittest

class FibonacciGeneratorTest(unittest.TestCase):

  def test_generate_fibonacci(self):
    # Test the Fibonacci generator for various inputs
    test_cases = [(0, []), (1, [0]), (2, [0, 1, 1]),
                  (10, [0, 1, 1, 2, 3, 5, 8]),
                  (100, [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89])]

    for n, expected_sequence in test_cases:
      with self.subTest(n=n):
        self.assertEqual(generate_fibonacci(n), expected_sequence)

if __name__ == ' __main__':
  unittest.main()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, we import the unittest module and write a test for the &lt;code&gt;generate_fibonacci&lt;/code&gt; function. An array of test cases is added with the limit being the first item in each tuple and the expected Fibonacci sequence as the second item. We then loop over the test cases and assert that the value returned from &lt;code&gt;generate_fibonacci(n)&lt;/code&gt; is equal to the expected Fibonacci sequence.&lt;/p&gt;

&lt;p&gt;Run the test and you should have a result in the teminal&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RcehhySj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1685036131839/4eadb206-82a3-4d6e-a629-c009c8ce2231.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RcehhySj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1685036131839/4eadb206-82a3-4d6e-a629-c009c8ce2231.png" alt="" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, looks like the test failed! An indicator that the &lt;code&gt;generate_fibonacci&lt;/code&gt; function is not working as expected and will need to be refactored to provide the desired result.&lt;/p&gt;

&lt;p&gt;When you critically look at the sequence from the &lt;code&gt;generate_fibonacci&lt;/code&gt; function, you can observe that the proceeding numbers are multiples of the preceding numbers -implying the problem could be in the while loop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def generate_fibonacci(n):
#.....
  while x &amp;lt; n:
    fibs.append(x)
    x = y
    y = x + y
  #......

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;from the while loop, after appending the initial &lt;code&gt;x&lt;/code&gt; value &lt;code&gt;(0)&lt;/code&gt; to the &lt;code&gt;fibs&lt;/code&gt; array, &lt;code&gt;x&lt;/code&gt; is set to the value of &lt;code&gt;y&lt;/code&gt; &lt;code&gt;(1)&lt;/code&gt;; &lt;code&gt;y&lt;/code&gt; becomes the sum of &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt; -adding 1 to the sequence. Thereafter, subsequent iterations generate multiples of the preceding number. This is not what we're trying to achieve!&lt;/p&gt;

&lt;p&gt;To solve the above problem, refactor the code using multiple variable assignment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def generate_fibonacci(n):
  x = 0
  y = 1
  fibs = []
  while x &amp;lt; n:
    fibs.append(x)
    x, y = y, x + y
  return fibs

print(generate_fibonacci(100))

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the code and you should have a result in your terminal&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WSuKuUVf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1685080509283/2e06b4c6-d466-46b7-a4c1-6df99e59580e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WSuKuUVf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1685080509283/2e06b4c6-d466-46b7-a4c1-6df99e59580e.png" alt="" width="800" height="133"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you have an accurate list of Fibonacci numbers of the specified limit and the test passed too!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;So what changed?&lt;/em&gt; Well, using multiple variable assignment made it possible to assign new values to &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; based on their existing values. In the previous implementation, reassigning the value of &lt;code&gt;x&lt;/code&gt; separately from &lt;code&gt;y&lt;/code&gt; meant &lt;code&gt;y&lt;/code&gt; would become the sum of the new value of &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; -providing inaccurate results.&lt;/p&gt;

&lt;p&gt;Besides reassigning variables based on their existing values, the multiple variable assignment technique is also commonly used when swapping values between variables as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tOhiza4x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1685084310246/2a0d099a-f425-4172-a0f7-b50e361c358d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tOhiza4x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1685084310246/2a0d099a-f425-4172-a0f7-b50e361c358d.png" alt="" width="750" height="179"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;If you made it this far you've understood Python variable assignment methods and how each of the methods is likely to impact your code's accuracy.&lt;/p&gt;

</description>
      <category>python</category>
      <category>variableassignment</category>
      <category>fibonacci</category>
      <category>variables</category>
    </item>
    <item>
      <title>How to serialize responses in nestjs</title>
      <dc:creator>Alwoch Sophia</dc:creator>
      <pubDate>Mon, 01 May 2023 08:56:30 +0000</pubDate>
      <link>https://dev.to/alwoch/how-to-serialize-responses-in-nestjs-4khk</link>
      <guid>https://dev.to/alwoch/how-to-serialize-responses-in-nestjs-4khk</guid>
      <description>&lt;p&gt;When writing APIs, you'll most likely have to return responses to the client. For example, when writing a sign-up API, you may be required to return the created user object to the client.&lt;/p&gt;

&lt;p&gt;An important step to take in development is ensuring that only the required amount of data is returned for performance reasons -and that It does not include sensitive information such as passwords that could compromise your users' accounts. This can be achieved by serializing responses before they are returned..&lt;/p&gt;

&lt;p&gt;In this tutorial, you'll learn how serialization works in nestjs and how to serialize your responses in nestjs&lt;/p&gt;

&lt;h2&gt;
  
  
  prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow along seamlessly, this article assumes you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;some experience building REST APIS with nodejs and nestjs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An understanding of nestjs project structure and terminologies such as decorators, modules, controllers, providers etc&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some experience programming in javascript and typescript&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How nestjs serialization works
&lt;/h2&gt;

&lt;p&gt;serialization in nestjs is enabled using the &lt;code&gt;ClassSerializerInterceptor.&lt;/code&gt; It intercepts the responses and serialises them to the desired format before returning them to the client. The &lt;code&gt;ClassSerializerInterceptor&lt;/code&gt; interceptor can be set at the application level to enable serialization by controllers -or at the service level for serialization by services.&lt;/p&gt;

&lt;p&gt;An entity class (serializer class) is created to define the shape of the data one would like to return to the client. The &lt;a href="https://github.com/typestack/class-transformer" rel="noopener noreferrer"&gt;class transformer&lt;/a&gt; package is then used to provide a set of rules to transform the data before it is returned to the client. The serialized data becomes an instance of the entity class and the returned value of a method handler as shown in the example below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example.
&lt;/h2&gt;

&lt;p&gt;This example is a citizen registration app where citizens signup to become users by providing their information. It demonstrates serializing data by excluding some information provided such as &lt;code&gt;password&lt;/code&gt; and includes the &lt;code&gt;citizenStatus&lt;/code&gt; -a computation derived from the provided date of birth.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set up:
&lt;/h3&gt;

&lt;p&gt;To get started, in your terminal, install &lt;a href="https://docs.nestjs.com/cli/overview" rel="noopener noreferrer"&gt;nestjs CLI&lt;/a&gt; if you do not have it installed already&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g @nestjs/cli

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the nest CLI to generate a new project boilerplate and select the package manager you'll be using&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nest new citizen_app

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;next, install some packages that will be required for this example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i --save class-validator class-transformer

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the root of your project, create a userData.json file to serve as data storage for this project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch userData.json

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rest Endpoints:
&lt;/h3&gt;

&lt;p&gt;With the set-up complete, regenerate a resource for the user and select generate REST endpoints&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nest g resource user

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A new user folder should be added to your src folder containing, service, controllers, dto, entities etc&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;create-user.dto.ts&lt;/code&gt;, define the properties that will be used to create the user. Add some validations to the properties using the &lt;a href="https://github.com/typestack/class-validator" rel="noopener noreferrer"&gt;class-validator&lt;/a&gt; package as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { IsNotEmpty, IsString, IsDateString, IsEmail } from 'class-validator';

export class CreateUserDto {
  @IsNotEmpty() //should not be empty
  @IsString() //should be a string
  firstname: string;

  @IsNotEmpty()
  @IsString()
  lastname: string;

  @IsDateString({ strict: true }) //should be in format 2022-07-15.
  dateOfBirth: Date;

  @IsEmail() //should be a valid email
  email: string;

  @IsNotEmpty()
  @IsString()
  password: string;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You have to enable global validations in your &lt;code&gt;src/main.ts&lt;/code&gt; &lt;code&gt;bootstrap()&lt;/code&gt; function for the validations to be applied. Add this code just before your &lt;code&gt;app.listen()&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.useGlobalPipes(new ValidationPipe())

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;user&lt;/code&gt; folder, create a new folder called &lt;code&gt;interfaces.&lt;/code&gt; create an interface for the created user&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface IUser {
  id: number;
  firstname: string;
  lastname: string;
  dateOfBirth: Date;
  email: string;
  password: string;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;src/user.service.ts&lt;/code&gt;, the &lt;code&gt;UserService&lt;/code&gt; class will need to have access to the data storage file to read and write to it. To achieve that, The &lt;code&gt;UserService&lt;/code&gt; class has to instantiate by reading the &lt;code&gt;userData.json&lt;/code&gt; file as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import * as fs from 'fs';
import * as path from 'path';
import {Injectable} from '@nestjs/commom';
import { CreateUserDto } from './dto/create-user.dto';
import { IUser } from './interfaces';

@Injectable()
export class UserService {
  private userData: IUser[];

  constructor() {
    fs.promises
      .readFile(path.join(__dirname, '../../userData.json'), 'utf-8')
      .then((data) =&amp;gt; {
        this.userData = JSON.parse(data);
      })
      .catch((err) =&amp;gt; {
        console.error(err);
      });
  }

  private saveUser() {
    fs.promises.writeFile(
      path.join(__dirname, '../../userData.json'),
      JSON.stringify(this.userData),
    );
  }
//the rest of the generated methods go here...
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Still in &lt;code&gt;src/user/user.service.ts&lt;/code&gt;, add some actual implementation to the rest of the method handlers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//continuation of userService class...
//create new user
  create(dto: CreateUserDto) {
    const existingUser = this.userData.find((user) =&amp;gt; user.email === dto.email);
    if (existingUser) throw new ConflictException('user already exists');

    const newUser: IUser = {
      id: this.userData.length + 1,
      firstname: dto.firstname,
      lastname: dto.lastname,
      dateOfBirth: dto.dateOfBirth,
      email: dto.email,
      password: dto.password,
    };
    this.userData.push(newUser); //add new user to userData
    this.saveUser();

    return newUser;
  }

// find all users
  findAll() {
    return this.userData;
  }

// find a user with id
  findOne(id: number) {
    const user = this.userData.find((user) =&amp;gt; user.id === id);
    if (!user) throw new NotFoundException('user not found');
    return user;
  }

// delete user
  remove(id: number) {
    const userIndex = this.userData.findIndex((user) =&amp;gt; user.id === id);
    if (userIndex === -1) throw new NotFoundException('user not found');
    this.userData.splice(userIndex, 1);
    this.saveUser();
  }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that in a real application, you'll have to secure your passwords before saving them by hashing them using a third-party package such as &lt;a href="https://www.npmjs.com/package/bcryptjs" rel="noopener noreferrer"&gt;bcrypt&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the &lt;code&gt;UserService&lt;/code&gt; fully implemented, start the server by running &lt;code&gt;npm run start:dev&lt;/code&gt; in your terminal and send some requests. You can use Postman, Insomnia or any other tool of your choice.&lt;/p&gt;

&lt;p&gt;The response from making a &lt;code&gt;POST&lt;/code&gt; request to the &lt;code&gt;user&lt;/code&gt; endpoint should look like this in Postman.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1682917494451%2Fc42c888c-8a9c-421c-b8dd-78cf09766cda.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1682917494451%2Fc42c888c-8a9c-421c-b8dd-78cf09766cda.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that among other properties returned in the response object, we have &lt;code&gt;password&lt;/code&gt; -which would compromise the security of your users' data. The plan is to have the password excluded from the response object. For this example, the &lt;code&gt;dateOfBirth&lt;/code&gt; property will also be excluded and instead, a &lt;code&gt;citizenStatus&lt;/code&gt; property -indicating whether the user is a child, adult or senior depending on their date of birth will be included.&lt;/p&gt;

&lt;h3&gt;
  
  
  Serializing the endpoints
&lt;/h3&gt;

&lt;p&gt;The plan is to use the &lt;code&gt;ClassSerializerInterceptor&lt;/code&gt; at the application level so that all the route handlers in the controller that are provided with an instance of the entity class (serializer class) can perform serialization.&lt;/p&gt;

&lt;p&gt;In your &lt;code&gt;src/main.ts&lt;/code&gt;, import the &lt;code&gt;ClassSerializerInterceptor&lt;/code&gt; from &lt;code&gt;@nestjs/common&lt;/code&gt; and add the interceptor globally. Your final &lt;code&gt;bootstrap()&lt;/code&gt; function should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { ClassSerializerInterceptor } from '@nestjs/common';
import { ValidationPipe } from '@nestjs/common';
import { NestFactory, Reflector } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe()); //set validations to the application level
  // 👇 apply transform to all responses
  app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector)));
  await app.listen(3000);
}
bootstrap();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create an entity class and supply a set of rules for transforming the data. Add this to your &lt;code&gt;src/user/entities/user.entity.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Exclude, Expose } from 'class-transformer';
import { IUser } from '../interfaces';

interface IUserEntity extends IUser {
  get citizenStatus(): CitizenStatus;
}

type CitizenStatus = 'Child' | 'Adult' | 'Senior';

export class UserEntity implements IUserEntity {
  id: number;
  firstname: string;
  lastname: string;
  email: string;

  @Exclude()
  dateOfBirth: Date;

  @Exclude()
  password: string;

  @Expose()
  get citizenStatus(): CitizenStatus {
    const birthDate = new Date(this.dateOfBirth).getFullYear();
    const currentYear = new Date().getFullYear();
    const age = currentYear - birthDate;
    if (age &amp;lt; 18) {
      return 'Child';
    } else if (age &amp;gt; 18 &amp;amp;&amp;amp; age &amp;lt; 60) {
      return 'Adult';
    } else {
      return 'Senior';
    }
  }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the provided snippet, the &lt;code&gt;@Exclude()&lt;/code&gt; decorator from the &lt;a href="https://github.com/typestack/class-transformer" rel="noopener noreferrer"&gt;class-transformer&lt;/a&gt; package is used to indicate that the &lt;code&gt;password&lt;/code&gt; and &lt;code&gt;dateOfBirth&lt;/code&gt; properties should be excluded from the response objects. On the other hand, the &lt;code&gt;citizenStatus&lt;/code&gt; property is indicated to be included using the &lt;code&gt;@Expose()&lt;/code&gt; decorator.&lt;/p&gt;

&lt;p&gt;Since &lt;code&gt;citizenStatus&lt;/code&gt; is not an actual property of the entity class -but rather a computed value based on the &lt;code&gt;dateOfBirth&lt;/code&gt; property, the &lt;code&gt;get&lt;/code&gt; keyword is used to define a getter method for &lt;code&gt;citizenStatus&lt;/code&gt; instead of a regular property.&lt;/p&gt;

&lt;p&gt;With the entity class created, the next step is to use it in the controller. Refactor your &lt;code&gt;src/user/user.controller.ts&lt;/code&gt;to match this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Controller, Get, Post, Body, Param, Delete } from '@nestjs/common';
import { UserService } from './user.service';
import { CreateUserDto } from './dto/create-user.dto';
import { UserEntity } from './entities/user.entity';

@Controller('user')
export class UserController {
  constructor(private readonly userService: UserService) {}

  @Post()
  create(@Body() createUserDto: CreateUserDto): UserEntity {
    return new UserEntity(this.userService.create(createUserDto));
  }

  @Get()
  findAll(): UserEntity[] {
    const users = this.userService.findAll();
    return users.map((user) =&amp;gt; new UserEntity(user));
  }

  @Get(':id')
  findOne(@Param('id') id: string): UserEntity {
    return new UserEntity(this.userService.findOne(+id));
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.userService.remove(+id);
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The controller's method handlers that will need to be serialized are refactored to return an instance of the entity class with the return values of the delegated service handlers. A return type of &lt;code&gt;UserEntity&lt;/code&gt; is also added.&lt;/p&gt;

&lt;p&gt;Restart your application and send some requests to confirm the serialiser is working as expected. The &lt;code&gt;GET&lt;/code&gt; request to fetch all users provides the following response:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1682922286821%2F637c4859-23c5-4e98-828e-d1033a8fb0a8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1682922286821%2F637c4859-23c5-4e98-828e-d1033a8fb0a8.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the response, you can tell the data has been properly serialized to the desired format.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;If you've made it to the end of this article, you've learnt how serialization works in nestjs and learnt hands-on to serialize data in nestjs. From the example, you can tell that among other things, you can return only a subset of an object and also make use of getters and setters.&lt;/p&gt;

&lt;p&gt;There are so many other transformations you can apply to your response objects and this tutorial only scratched the surface with those. To dive deep into transformations, feel free to read more on the &lt;a href="https://github.com/typestack/class-transformer" rel="noopener noreferrer"&gt;class-transformer Github&lt;/a&gt;. Also, check out the &lt;a href="https://docs.nestjs.com/techniques/serialization" rel="noopener noreferrer"&gt;nestjs docs&lt;/a&gt; on this same topic.&lt;/p&gt;

&lt;p&gt;The complete source code for this example can be found on Github &lt;a href="https://github.com/Alwoch/nestjs_serialization" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nestjs</category>
      <category>node</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Logging -and how to configure it in Python</title>
      <dc:creator>Alwoch Sophia</dc:creator>
      <pubDate>Mon, 23 Jan 2023 10:03:42 +0000</pubDate>
      <link>https://dev.to/alwoch/logging-and-how-to-configure-it-in-python-28i8</link>
      <guid>https://dev.to/alwoch/logging-and-how-to-configure-it-in-python-28i8</guid>
      <description>&lt;p&gt;As a developer, it is essential to stay on top of the changes in your application during development and production. Logging enables you to track events, features, errors and when they occur.&lt;/p&gt;

&lt;p&gt;This tutorial will take you through setting up basic logging to advanced concepts and will cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;what logging is&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;why logging is important&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The python logging module&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;logging levels&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;creating loggers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;storing logs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;formatting logs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;customising logs using the Colorlog package&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow along seamlessly, you may need to have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;a code editor such as &lt;a href="https://code.visualstudio.com/"&gt;VScode&lt;/a&gt; or an online IDE such as &lt;a href="https://replit.com/"&gt;replit&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;basic python programming experience&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;python and pip installed if you're using a code editor&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is logging?
&lt;/h2&gt;

&lt;p&gt;Logging is the process of recording information about an application's execution. This information may include and is not limited to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;events such as user actions, errors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;performance metrics such as response times and memory usage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;security events such as login attempts etc.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why logging is important
&lt;/h2&gt;

&lt;p&gt;Logging contributes significantly towards application health and here's why it should be configured:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Error tracking. Logging provides detailed information about errors, where and when they occur in your application making it easy for you to track and fix them easily.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Debugging. You can identify and fix bugs faster and more efficiently when you log information about your application's execution.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Auditing and monitoring. Logs provide information about how your application is being used and by whom.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security. Logging information on user actions, system events and other security-related information enables you to notice security breaches and respond to them in a timely fashion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compliance. Regulatory and compliance requirements may require companies to provide a record of activity and changes to their systems which can be referenced using the application's logs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Logging module.
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://docs.python.org/3/library/logging.html"&gt;Logging module&lt;/a&gt; in Python provides classes and methods required to set up logging functionality for your applications. It is included as part of the Python standard library and can be used without installing it. To use the logging module, import it as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#import the logging module
import logging

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code avails the different methods and attributes in the logging module for you to use. You can explore these attributes and methods by calling the &lt;code&gt;dir()&lt;/code&gt; method on the logging module and printing it to the console as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#print the logging module diretory
print(dir(logging))

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code outputs a list containing log levels, methods and classes to the console as shown in the following image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PvDhsQ-H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1673611714105/dcd8792a-1a9d-4963-9229-e705f52f8bd6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PvDhsQ-H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1673611714105/dcd8792a-1a9d-4963-9229-e705f52f8bd6.png" alt="console result when print(dir(logging)) is run" width="800" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can use the following criteria to make sense of the returned list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Logging levels are indicated by uppercase letters. These are generally considered constants for example &lt;code&gt;DEBUG, ERROR&lt;/code&gt;, &lt;code&gt;CRITICAL&lt;/code&gt; etc&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;classes are written in pascal's case for example &lt;code&gt;RootLogger&lt;/code&gt;, &lt;code&gt;LoggerAdapter&lt;/code&gt; etc&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;methods are written in camel case for example &lt;code&gt;getLogger&lt;/code&gt;, &lt;code&gt;getLevelName&lt;/code&gt; etc&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;private attributes are indicated by preceding underscores for example &lt;code&gt;_showwarning&lt;/code&gt;&lt;em&gt;,&lt;/em&gt; &lt;code&gt;_srcfile&lt;/code&gt; etc&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;special methods are indicated by preceding and proceeding double underscores.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While there's so much to work with in the logging module, this tutorial will use the logging levels, some of the classes and methods to show you how to configure logging for your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  logging levels
&lt;/h2&gt;

&lt;p&gt;Python uses logging levels to indicate the severity of a log message. This allows you to filter log messages based on their importance for example isolating critical logs to a different destination. The following table shows the log levels defined in the logging module, their numeric values and when you should use them.&lt;/p&gt;

&lt;p&gt;| Level | numeric value | use case |&lt;br&gt;
| &lt;code&gt;CRITICAL&lt;/code&gt; | 50 | Indicating a severe error |&lt;br&gt;
| &lt;code&gt;ERROR&lt;/code&gt; | 40 | Recording an error |&lt;br&gt;
| &lt;code&gt;WARNING&lt;/code&gt; | 30 | Indicating potential issues |&lt;br&gt;
| &lt;code&gt;INFO&lt;/code&gt; | 20 | Confirming expected behaviour |&lt;br&gt;
| &lt;code&gt;DEBUG&lt;/code&gt; | 10 | testing and debugging in development |&lt;br&gt;
| &lt;code&gt;NOTSET&lt;/code&gt; | 0 |&lt;/p&gt;

&lt;p&gt;In addition to the above constants, the logging module provides methods that can be used to indicate the severity of a log. These are lowercase versions of the above levels and are used by calling the method name on the logging object with a message as a parameter as shown in the snippet below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;logging.critical('This is a critical message')
logging.error('This is an error message')
logging.warning('This is a warning message')
logging.info('This is an info message')
logging.debug('This is a debugging message')

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the above code produces the following result in the console&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ptQYnfVv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1673621833351/0cfb73ec-7b2b-4287-a1c6-a5c082da266d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ptQYnfVv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1673621833351/0cfb73ec-7b2b-4287-a1c6-a5c082da266d.png" alt="console result from running the above python code" width="800" height="131"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the result in the console, you can observe that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;INFO&lt;/code&gt; and &lt;code&gt;DEBUG&lt;/code&gt; logs do not appear in the console. This is because the logging level is set to 30 -the numeric value for &lt;code&gt;WARNING&lt;/code&gt; by default. The logging module only outputs logs for logging levels greater than or equal to the set level.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The logs are populated in the format level-logger name-message. The logger name is set to &lt;code&gt;root&lt;/code&gt; by default -implying the root logger for cases where a logger name is not provided.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The output logs don't provide information on when the message was logged&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The logs are output to the console because a log destination is not set.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The logs shown above don't provide much context into what is happening. The default behaviour can be improved by properly configuring the loggerfo&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring logging
&lt;/h2&gt;

&lt;p&gt;The key steps involved in configuring standard logging include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;creating a logger&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;storing the logs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;formatting the logs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  creating a logger
&lt;/h3&gt;

&lt;p&gt;Creating a logger provides a basis for which other configurations for the logger are built. The &lt;code&gt;getLogger()&lt;/code&gt; method calls an existing logger by name or creates one if non-existent. Just below your import statement, copy and paste the following code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#create a logger
logger=logging.getLogger('basic_logger')
print(logger) #print the logger

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code creates a logger and stores it in the &lt;code&gt;logger&lt;/code&gt; variable. It also confirms the logger is created by printing the logger to the console. This should be your console result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--W7HdqFna--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1674043430793/29df5924-e897-46e7-b6cc-6585a2736312.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W7HdqFna--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1674043430793/29df5924-e897-46e7-b6cc-6585a2736312.png" alt="console result when the logger is printed" width="800" height="105"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;basic_logger&lt;/code&gt; has been created as confirmed by the console result. However, the result also shows that the default log level is set to WARNING -implying only log levels greater than or equal to &lt;code&gt;WARNING&lt;/code&gt; will be printed. For illustration purposes, we'll print all the log levels. To change the current set level to &lt;code&gt;DEBUG&lt;/code&gt;, call the &lt;code&gt;setLevel()&lt;/code&gt; function on the logger as seen in this snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#create a logger
logger=logging.getLogger('basic_logger')
#set the current level to DEBUG
logger.setLevel(logging.DEBUG)

print(logger) #print the logger
print(logger.level) #print the level

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the above code should confirm that the log level is set to &lt;code&gt;DEBUG&lt;/code&gt; and this should be the result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dzIoTgc7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1674044801104/6912a404-003b-4ada-bf7b-18fcb3a5287c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dzIoTgc7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1674044801104/6912a404-003b-4ada-bf7b-18fcb3a5287c.png" alt="console result showing the new log level and its numerical value" width="800" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that you've successfully created the logger, you can now add additional configurations to the created &lt;code&gt;logger&lt;/code&gt; variable&lt;/p&gt;

&lt;h3&gt;
  
  
  storing logs
&lt;/h3&gt;

&lt;p&gt;The logging module provides the &lt;a href="https://docs.python.org/3/library/logging.handlers.html"&gt;Handler&lt;/a&gt; class for determining where logs are stored. Several destinations may be used to store logs depending on the application and developer's needs. Some of these destinations include and are not limited to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;http: logs may be moved via POST request to a database&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;email: some developers may choose to have critical logs sent to an email&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;file: a file can be created on the server to which all the logs are populated.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A handler is created by initialising one or more destination &lt;a href="https://docs.python.org/3/library/logging.handlers.html#module-logging.handlers"&gt;handler classes&lt;/a&gt; and supplying it with a log level. A handler will only output logs for the specified log level or maintain the default level.&lt;/p&gt;

&lt;p&gt;This example illustrates how to store logs in a file using the &lt;a href="https://docs.python.org/3/library/logging.handlers.html#filehandler"&gt;Filehandler class&lt;/a&gt;. Copy this snippet and paste it below the logger you created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#create a file handler
file_handler = logging.FileHandler(filename='D:\\python\\pythonLogs.log',
                                   mode='w',
                                   encoding='utf-8')
#set the log level of the file handler
file_handler.setLevel(logging.DEBUG)
# add file handler to logger
logger.addHandler(file_handler)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Breaking down the code snippet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A file handler is created by initializing the &lt;code&gt;FileHandler&lt;/code&gt; class with a relative path to the preferred destination for the logs and assigned to the &lt;code&gt;file_handler&lt;/code&gt; variable. In this example, the file handler writes the logs in write mode. if you'd like to preserve the history of your logs and not overwrite them, you can safely ignore the mode and maintain the default append mode.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The log level of the handler is set to &lt;code&gt;DEBUG&lt;/code&gt; -meaning this handler will store all the log levels in this same file. if you'd like to store different log levels separately, you can create different handlers with different destinations for each of the log levels.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The handler is added to the logger&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the handler added to the logger, add the following test logs to your editor and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#print some example logging messages
logger.critical('This is a critical message')
logger.error('This is an error message')
logger.warning('This is a warning message')
logger.info('This is an info message')
logger.debug('This is a debugging message')

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result should be a pythonLogs.log file created at the specified destination with the logging messages as seen in the screenshot below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GS8mzhK1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1674064644706/875e19fc-77bf-4286-949a-14aeac872d4b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GS8mzhK1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1674064644706/875e19fc-77bf-4286-949a-14aeac872d4b.png" alt="logs appearing in the log file" width="800" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Formatting logs
&lt;/h3&gt;

&lt;p&gt;Up until this point, the printed logs only show the messages, however, information on the Log level and when the log was created would be useful.&lt;/p&gt;

&lt;p&gt;The logging module provides the &lt;a href="https://docs.python.org/3/library/logging.html#logging.Formatter"&gt;Formatter class&lt;/a&gt; for specifying the appearance of logs. The Formatter class is initialized with a format string created using &lt;a href="https://docs.python.org/3/library/logging.html#logrecord-attributes"&gt;the accepted log Record Attributes&lt;/a&gt; and passed to the handler to print the logs in the specified format, in the destination specified by the handler as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# create a formatter
formatter = logging.Formatter(
  '%(levelname)s- %(name)s-%(asctime)s - %(message)s')

# add formatter to file_handler
file_handler.setFormatter(formatter)

# add file handler to logger
logger.addHandler(file_handler)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, the &lt;code&gt;formatter&lt;/code&gt; is created using the log level names, the log name, the time and the message. The &lt;code&gt;formatter&lt;/code&gt; is added to the handler and the handler is then added to the logger.&lt;/p&gt;

&lt;p&gt;The following code snippet uses a &lt;code&gt;Dog&lt;/code&gt; class to demonstrate the functionality of the logging system we've created. The class is initialized using a dog name and logs the number of times a dog has been barked. If the dog is made to mark more than 3 times, an exception is raised. Add it to your editor and run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Dog:
    def __init__ (self, dogname):
        self.dogname = dogname
        self.count = 0

    def bark(self):
        try:
            self.count += 1
            logger.info(f"{self.dogname} barked {self.count} times")
            if self.count &amp;gt; 3:
                raise Exception(f"{self.dogname} cannot bark more than 3 times.")
            else:
                print("Woof!")
        except Exception as e:
            logger.error(e)
            raise

logger.info('initialising the Dog class')
mendy=Dog('Mendy')
mendy.bark()
mendy.bark()
mendy.bark()
mendy.bark()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should have the following results in your console and pythonLogs.log file respectively:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0Ef23dkx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1674196840939/1a1f3e3a-aecc-4c79-aea9-1049953c5c07.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0Ef23dkx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1674196840939/1a1f3e3a-aecc-4c79-aea9-1049953c5c07.png" alt="console result of running the Dog class" width="800" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uScMwMjW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1674196917890/b2d42ded-4162-4c54-bb91-5f0d873f1c09.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uScMwMjW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1674196917890/b2d42ded-4162-4c54-bb91-5f0d873f1c09.png" alt="pythonLogs.log file result" width="800" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;in the pythonLogs.log file, you can observe a change in the format of the logs and they now appear in the Level-log name-time-message format.&lt;/p&gt;

&lt;p&gt;still, on Formatting, you may have noticed that python logs appear in a uniform colour and it may be difficult for a developer to distinguish between the logs, especially during development. A third-party package called colorlog improves this behaviour.&lt;/p&gt;

&lt;h2&gt;
  
  
  colorlog package
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://pypi.org/project/colorlog/"&gt;colorlog&lt;/a&gt; package improves the built-in python logging module by enabling colour configurations for different log levels. It uses handers and formatters that work in a similar way to those in the logging module. The colorlog package is a third-party library and has to be installed to use it as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install colorlog

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;after you've installed colorlog, go ahead and import it in your file as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import colorlog

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with the colorlog methods now being available to use, copy and paste the colorlog configurations below into your editor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create a colored formatter
formatter = colorlog.ColoredFormatter(
    '%(log_color)s%(levelname)s:%(name)s:%(message)s',
    log_colors={
        'DEBUG': 'cyan',
        'INFO': 'green',
        'WARNING': 'yellow',
        'ERROR': 'red',
        'CRITICAL': 'red',
    }
)

# Create formatted logger
log = colorlog.getLogger('formatted_logger')
log.setLevel("DEBUG")

# Add a handler to the formatted_logger
handler = colorlog.StreamHandler()
#add formatter to handler
handler.setFormatter(formatter)
#add handler to logger
log.addHandler(handler)
# Log some messages
log.debug("This is a debug message")
log.info("This is an info message")
log.warning("This is a warning message")
log.error("This is an error message")
log.critical("This is a critical message")

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code snippet above creates a formatter and adds log colours to the format string as a&lt;code&gt;log_colors&lt;/code&gt; attribute. The &lt;code&gt;log_colors&lt;/code&gt; dictionary contains key value pairs of the log levels and the colors they should appear in. A &lt;code&gt;StreamHandler&lt;/code&gt; is initialized to create the logs in the console. The formatter is added to the handler -and the handler is then added to the logger. when you run this code, you should have coloured logs appear in your console as in the screenshot below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q7SQ6QVf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1674199350477/558e89d5-377c-4832-86aa-84bd19eb4c63.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q7SQ6QVf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1674199350477/558e89d5-377c-4832-86aa-84bd19eb4c63.png" alt="colored logs generated using colorlog package" width="800" height="120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;You've learnt how to configure logging using the logging module and how to add colour formatting to your logs using the colorlog package. The article illustrates only one of the ways logging can be configured using the logging module. You can challenge yourself to use a YAML file where you want to use multiple handlers or the &lt;code&gt;basicConfig()&lt;/code&gt; method where you need just a single handler. Also, you can explore using the &lt;a href="https://docs.python.org/3/library/logging.handlers.html"&gt;various handlers&lt;/a&gt; to send logs to destinations that were not illustrated in this article. You can check out the &lt;a href="https://docs.python.org/3/library/logging.html#"&gt;python docs&lt;/a&gt; for more on logging and find the source code used for this article on replit &lt;a href="https://replit.com/@salwoch/Python-Logging"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
      <category>logging</category>
    </item>
  </channel>
</rss>
