<?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: Bastien ANTOINE</title>
    <description>The latest articles on DEV Community by Bastien ANTOINE (@bastantoine).</description>
    <link>https://dev.to/bastantoine</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%2F528699%2F8c4957d0-ede4-48a2-bfb7-75a5cdfab024.jpeg</url>
      <title>DEV Community: Bastien ANTOINE</title>
      <link>https://dev.to/bastantoine</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bastantoine"/>
    <language>en</language>
    <item>
      <title>Debugging Python programs without an IDE</title>
      <dc:creator>Bastien ANTOINE</dc:creator>
      <pubDate>Wed, 29 Jun 2022 21:39:04 +0000</pubDate>
      <link>https://dev.to/bastantoine/debugging-python-programs-without-an-ide-2lmc</link>
      <guid>https://dev.to/bastantoine/debugging-python-programs-without-an-ide-2lmc</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: this article was originally published on my personal blog. Check it out &lt;a href="https://bastien-antoine.fr"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When writing a program, making sure it works the way it's supposed to is a crucial part of the process. This means you have to test your code, and you almost always end up with bugs that you have to debug.&lt;/p&gt;

&lt;p&gt;When you are using a IDE, you often have nice tools to do that, with the ability to place breakpoints, observe the call stack, the content of the locals... But sometimes you find yourself in situation where your program lives somewhere else and you can't use those nice modern tools, and you have to find an other solution.&lt;/p&gt;

&lt;p&gt;If you are using Python, have some good news for you: the standard lib comes with a basic debugger included, pdb which we'll discover today.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.towhat-is-pdb"&gt;What is pdb?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.tohow-to-use-it"&gt;How to use it?&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.tousing-run-inside-a-repl"&gt;Using &lt;code&gt;run()&lt;/code&gt; inside a REPL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.tosetting-a-breakpoint-with-settrace"&gt;Setting a breakpoint with &lt;code&gt;set_trace()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.tousing-the-builtin-breakpoint-function"&gt;Using the builtin &lt;code&gt;breakpoint()&lt;/code&gt; function&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.tointeracting-with-pdb"&gt;Interacting with pdb&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.tonote-on-the-syntax"&gt;Note on the syntax&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.toipdb-the-evolution"&gt;&lt;code&gt;ipdb&lt;/code&gt;, the evolution&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.tonote-on-running-ipdb-with-breakpoint"&gt;Note on running ipdb with &lt;code&gt;breakpoint()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.tosome-drawbacks"&gt;Some drawbacks&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.toan-interactive-terminal-is-required"&gt;An interactive terminal is required&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.tothe-interface-is-not-very-user-friendly"&gt;The interface is not very user-friendly&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  What is pdb?
&lt;/h1&gt;

&lt;p&gt;pdb, as in &lt;em&gt;Python DeBugger&lt;/em&gt;, is an &lt;em&gt;interactive source code debugger for Python programs&lt;/em&gt;. It is part of the standard library, which mean that if you have Python, you have it. Just like any debugger it features builtin breakpoints capabilities, context and stack introspection as well as code evaluation.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to use it?
&lt;/h1&gt;

&lt;p&gt;There are a basically three way to run a program under pdb. The first one is using the &lt;code&gt;run()&lt;/code&gt; function inside a REPL&lt;sup id="fnref1"&gt;1&lt;/sup&gt;, the second is by putting a breakpoint inside your code with the &lt;code&gt;set_trace()&lt;/code&gt; function. The last one will also set a breakpoint, but this time using the builtin &lt;code&gt;breakpoint()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Assume you have the following piece of code you want to debug:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# mymodule.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;math&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sqrt&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using &lt;code&gt;run()&lt;/code&gt; inside a REPL
&lt;/h2&gt;

&lt;p&gt;The first way to use pdb is bt using the &lt;a href="https://docs.python.org/3.10/library/pdb.html#pdb.run"&gt;&lt;code&gt;run()&lt;/code&gt;&lt;/a&gt; function inside a REPL&lt;sup id="fnref1"&gt;1&lt;/sup&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;mymodule&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;launch&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pdb&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"launch()"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After providing the name of the function to run to the &lt;code&gt;run()&lt;/code&gt; function, we find ourselves with a different shell, as we can see with the &lt;code&gt;(Pdb)&lt;/code&gt;. That's the pdb shell, where we can explore our code, set breakpoint, show the stack... We'll talk about how to interact with it later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting a breakpoint with &lt;code&gt;set_trace()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;An other way is by putting a breakpoint inside your code with the &lt;a href="https://docs.python.org/3.10/library/pdb.html#pdb.set_trace"&gt;&lt;code&gt;set_trace()&lt;/code&gt;&lt;/a&gt; function. When you put it inside your code, Python will stop the current execution each time it reaches it, and will launch a pdb shell for you to interact. Now assume I put a breakpoint inside the previous code at the beggining of the &lt;code&gt;launch()&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;  from math import sqrt
&lt;span class="gi"&gt;+ import pdb
&lt;/span&gt;
  def compute(a: int, b: int) -&amp;gt; float:
      c = a ** 2 + b ** 2
      c = sqrt(c)
      return c

  def launch():
&lt;span class="gi"&gt;+     pdb.set_trace()
&lt;/span&gt;      result = compute(3, 4)
      print(result)

  if __name__ == '__main__':
      launch()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I launch this updated script with the regular python (and not inside a REPL):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; python mymodule.py
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /home/user/mymodule.py&lt;span class="o"&gt;(&lt;/span&gt;11&lt;span class="o"&gt;)&lt;/span&gt;launch&lt;span class="o"&gt;()&lt;/span&gt;
-&amp;gt; result &lt;span class="o"&gt;=&lt;/span&gt; compute&lt;span class="o"&gt;(&lt;/span&gt;3, 4&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;Pdb&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We end up with basically the same input, where we can interact with pdb.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the builtin &lt;code&gt;breakpoint()&lt;/code&gt; function
&lt;/h2&gt;

&lt;p&gt;There's a third way to run pdb. It is quite similar to the previous one, but this time we'll be using a builtin function: &lt;a href="https://docs.python.org/3.10/library/functions.html#breakpoint"&gt;&lt;code&gt;breakpoint()&lt;/code&gt;&lt;/a&gt;. This function exists since Python 3.7, and acts as some kind of proxy to your debugger, allowing you to switch between various Python debugger, without having to update your code.&lt;/p&gt;

&lt;p&gt;Its default behavior is to call &lt;code&gt;pdb.set_trace()&lt;/code&gt; when called, which is what matters for us here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;  from math import sqrt
&lt;span class="gd"&gt;- import pdb
&lt;/span&gt;
  def compute(a: int, b: int) -&amp;gt; float:
      c = a ** 2 + b ** 2
      c = sqrt(c)
      return c

  def launch():
&lt;span class="gd"&gt;-     pdb.set_trace()
&lt;/span&gt;&lt;span class="gi"&gt;+     breakpoint()
&lt;/span&gt;      result = compute(3, 4)
      print(result)

  if __name__ == '__main__':
      launch()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I launch this updated script with the regular python (and not inside a REPL):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; python mymodule.py
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /home/user/mymodule.py&lt;span class="o"&gt;(&lt;/span&gt;11&lt;span class="o"&gt;)&lt;/span&gt;launch&lt;span class="o"&gt;()&lt;/span&gt;
-&amp;gt; result &lt;span class="o"&gt;=&lt;/span&gt; compute&lt;span class="o"&gt;(&lt;/span&gt;3, 4&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;Pdb&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see that we end up with the same output as when we were using &lt;code&gt;pdb.set_trace()&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Interacting with pdb
&lt;/h1&gt;

&lt;p&gt;As you may have noticed, all interaction with pdb must be done using the keyboard, as it is the case with everything that happens inside a terminal. As such, there are a few commands builtin that allows you to interact with it. Let's run over the most interesting ones.&lt;/p&gt;

&lt;p&gt;THe official doc of the &lt;a href="https://docs.python.org/3.10/library/pdb.html"&gt;pdb module&lt;/a&gt; presents a list of all the available commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Note on the syntax
&lt;/h2&gt;

&lt;p&gt;Some of them have a both short and long syntax, which mean you can use either one of them for the same result. They are written like this, with the long form between parenthesis: &lt;code&gt;my(command)&lt;/code&gt;. For the previous example, &lt;code&gt;my&lt;/code&gt; is the short version, while &lt;code&gt;mycommand&lt;/code&gt; is the long.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: all the excerpts shown below have been reduced for the sake of readibility. If you try them yourself, you might see a bit more verbosity, but the core stays the same.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  l(ist)/ll
&lt;/h2&gt;

&lt;p&gt;These two commands are really similar: they both print the source code for the current file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;l(ist)&lt;/code&gt; will print 11 lines around the current line being executed (ie. 5 lines before, the line executed and 5 lines after)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ll&lt;/code&gt; will print all the source code for the current function&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The current line in the current frame is indicated by &lt;code&gt;-&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ll&lt;/span&gt;
  &lt;span class="mi"&gt;4&lt;/span&gt;     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="mi"&gt;5&lt;/span&gt;         &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="mi"&gt;6&lt;/span&gt;         &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="mi"&gt;7&lt;/span&gt;  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;
  &lt;span class="mi"&gt;2&lt;/span&gt;     &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pdb&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;set_trace&lt;/span&gt;
  &lt;span class="mi"&gt;3&lt;/span&gt;
  &lt;span class="mi"&gt;4&lt;/span&gt;     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="mi"&gt;5&lt;/span&gt;         &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="mi"&gt;6&lt;/span&gt;         &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="mi"&gt;7&lt;/span&gt;  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
  &lt;span class="mi"&gt;8&lt;/span&gt;
  &lt;span class="mi"&gt;9&lt;/span&gt;     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
 &lt;span class="mi"&gt;10&lt;/span&gt;         &lt;span class="n"&gt;set_trace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="mi"&gt;11&lt;/span&gt;         &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="mi"&gt;12&lt;/span&gt;         &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  c(ont(inue))
&lt;/h2&gt;

&lt;p&gt;This command will simply continue the executions of the program, until the next breakpoint, the end of the program, or any error raised.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ll&lt;/span&gt;
  &lt;span class="mi"&gt;4&lt;/span&gt;     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="mi"&gt;5&lt;/span&gt;         &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="mi"&gt;6&lt;/span&gt;         &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="mi"&gt;7&lt;/span&gt;  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;span class="mf"&gt;5.0&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;computer&lt;/span&gt; &lt;span class="o"&gt;~/&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  q(uit)
&lt;/h2&gt;

&lt;p&gt;This command will simply stop the execution of the program and exits right away.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;computer&lt;/span&gt; &lt;span class="o"&gt;~/&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;mymodule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt;
&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;
&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;
&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;
&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;quit&lt;/span&gt;
&lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s"&gt;"/home/user/mymodule.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s"&gt;"/home/user/mymodule.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;launch&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s"&gt;"/home/user/mymodule.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s"&gt;"/home/user/mymodule.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s"&gt;"/usr/lib/python3.7/bdb.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;trace_dispatch&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dispatch_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s"&gt;"/usr/lib/python3.7/bdb.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;113&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;dispatch_line&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quitting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;BdbQuit&lt;/span&gt;
&lt;span class="n"&gt;bdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BdbQuit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;: Be careful when using this command, especially when you are using handlers that need to be properly closed, like file handlers or database connections. If the code you are debugging doesn't properly close them in case of error, you might end up with side errors because those handlers weren't properly closed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Check out below the explanation of the &lt;code&gt;s(tep)&lt;/code&gt; and &lt;code&gt;n(ext)&lt;/code&gt; commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  p/pp
&lt;/h2&gt;

&lt;p&gt;evaluate and (pretty) prints an expression in the current context&lt;/p&gt;

&lt;p&gt;These two commands are really similar. They both evaluate a given expression in the current context and print its value. &lt;code&gt;p&lt;/code&gt; will print just like the regular builtin &lt;code&gt;print()&lt;/code&gt; function does, while &lt;code&gt;pp&lt;/code&gt; will pretty-print using the &lt;a href="https://docs.python.org/3.10/library/pprint.html#module-pprint"&gt;&lt;code&gt;pprint&lt;/code&gt; module&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"a=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, b=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
&lt;span class="s"&gt;'a=3, b=4'&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;pp&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="p"&gt;...,&lt;/span&gt;
 &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;43&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;46&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  n(ext)/s(tep)
&lt;/h2&gt;

&lt;p&gt;These two commands are almost the same. They allow you to move forward in you program, one line at a time, by executing the next line.&lt;/p&gt;

&lt;p&gt;Their behavior differ when the next step to execute is a call to a function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;n(ext)&lt;/code&gt; will simply execute the function&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;s(tep)&lt;/code&gt; will enter the function and stops at the function signature (ie. the &lt;code&gt;def myFunc(*args, **kwargs):&lt;/code&gt;), allowing you to go further using &lt;code&gt;n(ext)&lt;/code&gt; or &lt;code&gt;s(tep)&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ll&lt;/span&gt;
  &lt;span class="mi"&gt;9&lt;/span&gt;     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
 &lt;span class="mi"&gt;10&lt;/span&gt;         &lt;span class="n"&gt;set_trace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="mi"&gt;11&lt;/span&gt;  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;     &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="mi"&gt;12&lt;/span&gt;         &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt;
&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;
&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;
&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;
&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;w(here)&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This command prints the stack trace, with the most recent stack at the bottom.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;
  &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;home&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;mymodule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;home&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;mymodule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;u(p)/d(own)&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;These two commands allows you to move up and down inside the stack. &lt;code&gt;u(p)&lt;/code&gt; will go to an older stack, ie. up in the list, while &lt;code&gt;d(own)&lt;/code&gt; will go to a newer one, ie. one at the bottom of the list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt;
&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;
 &lt;span class="mi"&gt;10&lt;/span&gt;         &lt;span class="n"&gt;set_trace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="mi"&gt;11&lt;/span&gt;         &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="mi"&gt;12&lt;/span&gt;         &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="mi"&gt;13&lt;/span&gt;
 &lt;span class="mi"&gt;14&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="mi"&gt;15&lt;/span&gt;  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;     &lt;span class="n"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;EOF&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;down&lt;/span&gt;
&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;
  &lt;span class="mi"&gt;6&lt;/span&gt;         &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="mi"&gt;7&lt;/span&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
  &lt;span class="mi"&gt;8&lt;/span&gt;
  &lt;span class="mi"&gt;9&lt;/span&gt;     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
 &lt;span class="mi"&gt;10&lt;/span&gt;         &lt;span class="n"&gt;set_trace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="mi"&gt;11&lt;/span&gt;  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;     &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="mi"&gt;12&lt;/span&gt;         &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="mi"&gt;13&lt;/span&gt;
 &lt;span class="mi"&gt;14&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="mi"&gt;15&lt;/span&gt;         &lt;span class="n"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;EOF&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  r(eturn)
&lt;/h2&gt;

&lt;p&gt;This command is useful when you are inside a function. It will continue its execution until it raises or returns.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ll&lt;/span&gt;
  &lt;span class="mi"&gt;4&lt;/span&gt;     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="mi"&gt;5&lt;/span&gt;  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;     &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="mi"&gt;6&lt;/span&gt;         &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="mi"&gt;7&lt;/span&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;
&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;Return&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;home&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;mymodule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="mf"&gt;5.0&lt;/span&gt;
&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ll&lt;/span&gt;
  &lt;span class="mi"&gt;4&lt;/span&gt;     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="mi"&gt;5&lt;/span&gt;         &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="mi"&gt;6&lt;/span&gt;         &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="mi"&gt;7&lt;/span&gt;  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  a(rgs)
&lt;/h2&gt;

&lt;p&gt;This command is really useful when you are insed the scope of a function, as it will print the args this function has been called with.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  interact
&lt;/h2&gt;

&lt;p&gt;The command &lt;code&gt;interact&lt;/code&gt; can be considered as an evolution of the two above. It will enter in a classic REPL, with the locals of the current scope loaded in the globals, meaning you can interact with it, just like in a regular Python console.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;interact&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;interactive&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pprint&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pprint&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pprint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;locals&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'__annotations__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
 &lt;span class="s"&gt;'__builtins__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="s"&gt;'builtins'&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;built&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s"&gt;'__cached__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s"&gt;'__doc__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s"&gt;'__file__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'/home/user/mymodule.py'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s"&gt;'__loader__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;_frozen_importlib_external&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SourceFileLoader&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="mh"&gt;0x107bf5ca0&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s"&gt;'__name__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s"&gt;'__package__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s"&gt;'__return__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s"&gt;'__spec__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s"&gt;'compute'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="mh"&gt;0x107c41310&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s"&gt;'launch'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;launch&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="mh"&gt;0x107e0e940&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s"&gt;'pprint'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;pprint&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="mh"&gt;0x1082c6c10&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s"&gt;'set_trace'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;set_trace&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="mh"&gt;0x1082df700&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s"&gt;'sqrt'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;built&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# Ctrl+D to exit and return to the pdb console
&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="n"&gt;exiting&lt;/span&gt; &lt;span class="n"&gt;InteractiveConsole&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pdb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  &lt;code&gt;ipdb&lt;/code&gt;, the evolution
&lt;/h1&gt;

&lt;p&gt;Do you know IPython? It is a modern Python console that extends the capabilities of the classic builtin Python shell by offering introspection, tab completion, syntaxing coloring, as well as history. If you don't know it, I can't recommend it enough. More information can be found in its &lt;a href="https://github.com/ipython/ipython"&gt;GitHub page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Based on this evolved console, some people have designed an evolved version of pdb that uses this REPL to bring all the cool features of IPython inside pdb: it is called &lt;code&gt;ipdb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once you have installed it using &lt;code&gt;pip&lt;/code&gt;, like any regular Python package, you can use like the same way you would use pdb:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- import pdb
&lt;/span&gt;&lt;span class="gi"&gt;+ import ipdb
&lt;/span&gt;
  def compute(a: int, b: int) -&amp;gt; float:
      c = a ** 2 + b ** 2
      c = sqrt(c)
      return c

  def launch():
&lt;span class="gd"&gt;-     pdb.set_trace()
&lt;/span&gt;&lt;span class="gi"&gt;+     ipdb.set_trace()
&lt;/span&gt;      result = compute(3, 4)
      print(result)

  if __name__ == '__main__':
      launch()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once run, the commands are the same as with pdb, excpet with IPython formatting applied (which you can't really see with the markdown formatting applied here. You'll have to either trust me or try it by yourself&lt;sup id="fnref2"&gt;2&lt;/sup&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;computer&lt;/span&gt; &lt;span class="o"&gt;~/&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;mymodule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
     &lt;span class="mi"&gt;10&lt;/span&gt;     &lt;span class="n"&gt;set_trace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;     &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="mi"&gt;12&lt;/span&gt;     &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ipdb&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ll&lt;/span&gt;
      &lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
     &lt;span class="mi"&gt;10&lt;/span&gt;     &lt;span class="n"&gt;set_trace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;     &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="mi"&gt;12&lt;/span&gt;     &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="mi"&gt;13&lt;/span&gt;

&lt;span class="n"&gt;ipdb&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt;
&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;
      &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="o"&gt;----&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="mi"&gt;5&lt;/span&gt;     &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="n"&gt;ipdb&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;
      &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;----&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;     &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
      &lt;span class="mi"&gt;6&lt;/span&gt;     &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ipdb&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="n"&gt;ipdb&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Note on running ipdb with &lt;code&gt;breakpoint()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;As said above, since Python 3.7, there's the builtin command &lt;code&gt;breakpoint()&lt;/code&gt; that allows to call a Python debugger using a single command. The default behavior of this command is to run &lt;code&gt;pdb.set_trace()&lt;/code&gt; when called. If you are using ipdb, you can change this behavior so that it uses this debugger instead.&lt;/p&gt;

&lt;p&gt;To do that you'll have to set the environment variable &lt;a href="https://docs.python.org/3.10/using/cmdline.html#envvar-PYTHONBREAKPOINT"&gt;&lt;code&gt;PYTHONBREAKPOINT&lt;/code&gt;&lt;/a&gt; to &lt;code&gt;ipdb.set_trace&lt;/code&gt;, so that Python will know which debugger to use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- import ipdb
&lt;/span&gt;
  def compute(a: int, b: int) -&amp;gt; float:
      c = a ** 2 + b ** 2
      c = sqrt(c)
      return c

  def launch():
&lt;span class="gd"&gt;-     ipdb.set_trace()
&lt;/span&gt;&lt;span class="gi"&gt;+     breakpoint()
&lt;/span&gt;      result = compute(3, 4)
      print(result)

  if __name__ == '__main__':
      launch()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;computer&lt;/span&gt; &lt;span class="o"&gt;~/&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;export&lt;/span&gt; &lt;span class="n"&gt;PYTHONBREAKPOINT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ipdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_trace&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;computer&lt;/span&gt; &lt;span class="o"&gt;~/&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;mymodule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
     &lt;span class="mi"&gt;10&lt;/span&gt;     &lt;span class="n"&gt;set_trace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;     &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="mi"&gt;12&lt;/span&gt;     &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ipdb&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Some drawbacks
&lt;/h1&gt;

&lt;p&gt;Now, like every nice tools, pdb, and its modern version ipdb, have some issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  An interactive terminal is required
&lt;/h2&gt;

&lt;p&gt;This may sound obvious, but I can assure you sometimes you forget about this and are reminded the hard way when you are trying to debug a application that's inside a Docker container.&lt;/p&gt;

&lt;p&gt;To be a bit more precise, to be able to properly use (i)pdb, you need to have access to a terminal in which you have access to both its input and output file descriptors, so that you can send commands to (i)pdb and see the output of the debugger.&lt;/p&gt;

&lt;p&gt;This means that if you are trying to debug an application that's running inside a container, a VM, or even a Kubernetes pod, and where you don't have any acces further than the logs, you'll have to find another solution.&lt;/p&gt;

&lt;p&gt;In this case, there are some pdb extensions that allows you to connect to the debugger using telnet, but that will the subject of a next article.&lt;/p&gt;

&lt;h2&gt;
  
  
  The interface is not very user-friendly
&lt;/h2&gt;

&lt;p&gt;As you may have noticed, the interface isn't really user-friendly, if we can even call it a real user interface. You have to remember where you are in your code, you can quickly see the content of your current context, setting new breakpoints within (i)pdb is kinda hard...&lt;/p&gt;

&lt;p&gt;This may be enough for some small applications, but once you start to debug more complex programs, this might become hard to use, if not impossible. In this you may find some more advanced tools more useful, like pudb. pudb is a console-based visual debugger for Python that is absolutely awesome, but I'll save the presentation for a next article.&lt;/p&gt;

&lt;h1&gt;
  
  
  Sources
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3.10/library/pdb.html"&gt;Python documentation - pdb — The Python Debugger&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/gotcha/ipdb"&gt;Integration of IPython pdb&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;the REPL, or &lt;em&gt;Read-Eval-Print Loop&lt;/em&gt;, is the fancy name of the console, or shell. Its name comes from its design as it is a &lt;em&gt;loop&lt;/em&gt; where each iteration consists of the same three steps: ↩&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;*read*ing of the user input&lt;/li&gt;
&lt;li&gt;*eval*uation of the input&lt;/li&gt;
&lt;li&gt;*print*ing of the result&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;


&lt;li id="fn2"&gt;

&lt;p&gt;You definitely should! ↩&lt;/p&gt;


&lt;/li&gt;


&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>Discovering Python Namespace Packages</title>
      <dc:creator>Bastien ANTOINE</dc:creator>
      <pubDate>Sun, 09 Jan 2022 15:02:18 +0000</pubDate>
      <link>https://dev.to/bastantoine/discovering-python-namespace-packages-4gi3</link>
      <guid>https://dev.to/bastantoine/discovering-python-namespace-packages-4gi3</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: this article was originally published on my personal blog. Check it out &lt;a href="https://bastien-antoine.fr"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In a recent &lt;a href="https://bastien-antoine.fr/2021/10/playing-with-python-path-attribute.md"&gt;post about the &lt;code&gt;__path__&lt;/code&gt; attribute&lt;/a&gt;, I explained that it would be possible to manipulate a library's path to dynamically extend its functionalities. At the end of my article I detailed that this possibility has already been thought of was integrated in the import system since Python 3.3 with &lt;a href="https://www.python.org/dev/peps/pep-0420/"&gt;PEP 420, under the name of namespace package&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Today I'd like to go a bit more in details about this.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.towhat-is-a-package-in-python"&gt;What is a package in Python?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.tothe-specificity-of-the-namespace-packages"&gt;The specificity of the namespace packages&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.todifferences-with-the-regular-packages"&gt;Differences with the regular packages&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.tostep-by-step-basic-example"&gt;Step by step basic example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.todynamic-loading-of-package-parts"&gt;Dynamic loading of package parts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.tolimitations"&gt;Limitations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.topossible-usage"&gt;Possible usage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.tomore-concrete-example"&gt;More concrete example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  What is a package in Python?
&lt;/h1&gt;

&lt;p&gt;The &lt;a href="https://docs.python.org/3/glossary.html#term-package"&gt;Python glossary&lt;/a&gt; defines a package as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A Python module which can contain submodules or recursively, subpackages. Technically, a package is a Python module with a &lt;code&gt;__path__&lt;/code&gt; attribute.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So a package in Python is basically a set of &lt;code&gt;.py&lt;/code&gt; files (modules) organized in subdirectories (subpackages).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;__path__&lt;/code&gt; attribute is specific to the packages. It is used by the import system when trying to import modules of subpackages. Basically its function is the same as &lt;code&gt;sys.path&lt;/code&gt;, but limited to the scope of a package. I'll let you check out &lt;a href="https://bastien-antoine.fr/2021/10/playing-with-python-path-attribute.md"&gt;my article on the &lt;code&gt;__path__&lt;/code&gt; attribute&lt;/a&gt; about it for more information.&lt;/p&gt;

&lt;h1&gt;
  
  
  The specificity of the namespace packages
&lt;/h1&gt;

&lt;p&gt;A namespace package is a special kind of Python package: among other differences with the regular packages, the most important and notable difference is that &lt;em&gt;its source files can be splited across multiple locations&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This means that the following structure can be considered a namespace package, named &lt;code&gt;parent&lt;/code&gt; (I'll explain later on how this can be used):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/home/myUser/dev/
└── package/
    └── parent/
        └── child/
            └── foo.py
/var/usr/lib
└── package/
    └── parent/
        └── child/
            └── bar.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now with the following example, I would have two distinct packages, both named &lt;code&gt;parent&lt;/code&gt;, one in &lt;code&gt;/home/myUser/dev/&lt;/code&gt; and another in &lt;code&gt;/var/usr/lib&lt;/code&gt;&lt;sup id="fnref1"&gt;1&lt;/sup&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/home/myUser/dev/
└── package/
    └── parent/
        ├── __init__.py
        └── child/
            ├── __init__.py
            └── foo.py
/var/usr/lib
└── package/
    └── parent/
        ├── __init__.py
        └── child/
            ├── __init__.py
            └── bar.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Differences with the regular packages
&lt;/h2&gt;

&lt;p&gt;Like I already mentioned, the most notable difference between regular and namespace packages is that the latter can be splitted across multiple locations.&lt;/p&gt;

&lt;p&gt;This ability to split the sources also impacts the package's &lt;code&gt;__path__&lt;/code&gt; attribute: instead of being a list with a single element being the path of the package's &lt;code&gt;__init__.py&lt;/code&gt;, &lt;em&gt;it is an iterable of paths, containing all the locations of the package's sources&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Keen eyes might have noticed also that I ommitted the &lt;code&gt;__init__.py&lt;/code&gt; files in the structure of the namespace package example above. That's not a mistake, actually &lt;em&gt;namespace package are recognized and detected by the Python import system by their lack of &lt;code&gt;__init__.py&lt;/code&gt; files&lt;/em&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Step by step basic example
&lt;/h1&gt;

&lt;p&gt;Take the following structure as example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/home/myUser/dev/
└── packageExtension/
    └── parent/
        └── child/
            └── bar.py
/var/usr/lib
└── mainPackage/
    └── parent/
        └── child/
            └── foo.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make it work as a namespace package, we first need to make sure that both sources can be found in &lt;code&gt;sys.path&lt;/code&gt;. For the sake of the examples we'll add them by hand in it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="s"&gt;'/var/usr/lib/mainPackage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'/home/myUser/dev/packageExtension'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can try to load the &lt;code&gt;parent&lt;/code&gt; package, and see where Python finds its source files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# Continue from previous stage
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;parent&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__path__&lt;/span&gt;
&lt;span class="n"&gt;_NamespacePath&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="s"&gt;'/var/usr/lib/mainPackage/parent'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'/home/myUser/dev/packageExtension/parent'&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What's interesting here is the value of &lt;code&gt;parent.__path__&lt;/code&gt;: like said before, it's an iterable of strings for all the locations in &lt;code&gt;sys.path&lt;/code&gt; where a namespace package named &lt;code&gt;parent&lt;/code&gt; has been found.&lt;/p&gt;

&lt;p&gt;Now if we try to import the &lt;code&gt;child&lt;/code&gt; package, we should have the same thing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# Continue from previous stage
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;parent.child&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__path__&lt;/span&gt;
&lt;span class="n"&gt;_NamespacePath&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="s"&gt;'/var/usr/lib/mainPackage/parent/child'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'/home/myUser/dev/packageExtension/parent/child'&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now we can import both &lt;code&gt;foo&lt;/code&gt; and &lt;code&gt;bar&lt;/code&gt; modules under the same package name, even though they are in different locations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# Continue from previous stage
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;parent.child.foo&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;
&lt;span class="s"&gt;'/var/usr/lib/mainPackage/parent/child/foo.py'&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;parent.child.bar&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;
&lt;span class="s"&gt;'/home/myUser/dev/packageExtension/parent/child/bar.py'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Dynamic loading of package parts
&lt;/h1&gt;

&lt;p&gt;Now we've seen that to be able to load differents portions of a namespace package, first they all need to be accessible under &lt;code&gt;sys.path&lt;/code&gt;. What's cool is that if during the run, a new portion of a namespace package that's already imported were to be added to &lt;code&gt;sys.path&lt;/code&gt;, it'll be able to be loaded under the same namespace package.&lt;/p&gt;

&lt;p&gt;Take the following structure as example. It the same as previously, but with &lt;code&gt;/home/myOtherUser/dev/otherPackageExtension/&lt;/code&gt; added:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/home/myUser/dev/
└── packageExtension/
    └── parent/
        └── child/
            └── bar.py
/home/myOtherUser/dev/
└── otherPackageExtension/
    └── parent/
        └── child/
            └── baz.py
/var/usr/lib
└── mainPackage/
    └── parent/
        └── child/
            └── foo.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if we continue back where we left the previous example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# Continue from previous stage
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__path__&lt;/span&gt;
&lt;span class="n"&gt;_NamespacePath&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="s"&gt;'/var/usr/lib/mainPackage/parent'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'/home/myUser/dev/packageExtension/parent'&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;parent.child.baz&lt;/span&gt;
&lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;stdin&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nb"&gt;ModuleNotFoundError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;No&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="n"&gt;named&lt;/span&gt; &lt;span class="s"&gt;'parent.child.baz'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if we add &lt;code&gt;/home/myOtherUser/dev/otherPackageExtension/&lt;/code&gt; to &lt;code&gt;sys.path&lt;/code&gt;, the namespace package &lt;code&gt;parent&lt;/code&gt;'s &lt;code&gt;__path__&lt;/code&gt; should be recomputed to include the newly found portion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# Continue from previous stage
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/home/myOtherUser/dev/otherPackageExtension/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;...,&lt;/span&gt;
  &lt;span class="s"&gt;'/var/usr/lib/mainPackage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'/home/myUser/dev/packageExtension'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'/home/myOtherUser/dev/otherPackageExtension'&lt;/span&gt;
  &lt;span class="p"&gt;...,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__path__&lt;/span&gt;
&lt;span class="n"&gt;_NamespacePath&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="s"&gt;'/var/usr/lib/mainPackage/parent'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'/home/myUser/dev/packageExtension/parent'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'/home/myOtherUser/dev/otherPackageExtension/parent'&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which mean we can now import &lt;code&gt;parent.child.baz&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# Continue from previous stage
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;parent.child.baz&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;baz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;
&lt;span class="s"&gt;'/home/myUser/dev/otherPackageExtension/parent/child/baz.py'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Limitations
&lt;/h1&gt;

&lt;p&gt;There are some limitations to this :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;All portions of a namespace package must be declared as namespace packages (ie. without &lt;code&gt;__init__.py&lt;/code&gt; files). So the following is a namespace package with 2 portions (one in &lt;code&gt;/home/myUser/dev/packageExtension&lt;/code&gt; and one in &lt;code&gt;/var/usr/lib/mainPackage&lt;/code&gt;):
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/home/myUser/dev/
└── packageExtension/
    └── parent/
        └── child/
            └── bar.py
/var/usr/lib
└── mainPackage/
    └── parent/
        └── child/
            └── foo.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the following is not (note the &lt;code&gt;__init__.py&lt;/code&gt; inside &lt;code&gt;/home/myUser/dev/packageExtension&lt;/code&gt;), even though &lt;code&gt;/var/usr/lib/mainPackage&lt;/code&gt; is a namespace package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/home/myUser/dev/
└── packageExtension/
    ├── __init__.py
    └── parent/
        └── child/
            └── bar.py
/var/usr/lib
└── mainPackage/
    └── parent/
        └── child/
            └── foo.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;All the portions of a namespace package must be foundable in &lt;code&gt;sys.path&lt;/code&gt;, though they don't have to be already in it when loading the namespace package, the &lt;code&gt;__path__&lt;/code&gt; is dynamically computed.&lt;/p&gt;

&lt;p&gt;This point has an implication on the performances: because the path is recomputed each time a portion is loaded, the importation of a module of package can take a bit more time with a namespace package, than with a regular one.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Possible usage
&lt;/h1&gt;

&lt;p&gt;Now that we've discussed a bit the theory and seen a few examples, let's try to figure out real world applications. I've found two categories of usage of namespace applications:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;A unique interface for different portions of packages provided by various vendors.&lt;/p&gt;

&lt;p&gt;Imagine a low-level package that allows you to access various informations on your system, both software and hardware. You could have something that look a bit like this, where each part is provided by the manufacturer of the part at stake:&lt;br&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gpu_vendor/
└── system_management/
    └── hardware/
        └── gpu.py
cpu_vendor/
└── system_management/
    └── hardware/
        └── cpu.py
ram_vendor/
└── system_management/
    └── hardware/
        └── ram.py
os_vendor/
└── system_management/
    └── software/
        └── os.py
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this structure, and assuming all the portions are accessible within &lt;code&gt;sys.path&lt;/code&gt;, you'd have a single namespace package &lt;code&gt;system_management&lt;/code&gt; under which you could import &lt;code&gt;system_management.hardware.gpu&lt;/code&gt; or &lt;code&gt;system_management.software.os&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Adding optional extensions to a package&lt;/p&gt;

&lt;p&gt;In this example you would have a main namespace package that provides basic functionalities which you could extend at will, by installing other portions. Have a look at the next section for a more concrete example.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  More concrete example
&lt;/h1&gt;

&lt;p&gt;Let's take the example of an image manipulation library. It has a base library, and additional extensions that allows the manipulation of various type of images (jpg, png,...). It has the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example/
├── baseLib/
│   └── img_lib/
│       └── lib/
│           ├── base.py
│           └── settings.py
├── jpg/
│   └── img_lib/
│       └── lib/
│           └── jpg.py
├── gif/
│   └── img_lib/
│       └── lib/
│           └── gif.py
├── png/
│   └── img_lib/
│       └── lib/
│           └── png.py
└── svg/
    └── img_lib/
        └── lib/
            └── svg.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each image module simply declares its &lt;a href="https://developer.mozilla.org/fr/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types"&gt;mimetype&lt;/a&gt; with the constant &lt;code&gt;MIMETYPE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;base&lt;/code&gt; module reads the list of extensions declared in &lt;code&gt;settings.py&lt;/code&gt;, and will load them. After that, it'll be able to show the mimetype of all the extensions available.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# For the sake of the example, add all the portions of the namespace package in sys.path by hand.
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getcwd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;/&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
   &lt;span class="p"&gt;...:&lt;/span&gt;     &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getcwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;'baseLib'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
   &lt;span class="p"&gt;...:&lt;/span&gt;     &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getcwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;'png'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
   &lt;span class="p"&gt;...:&lt;/span&gt;     &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getcwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;'jpg'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
   &lt;span class="p"&gt;...:&lt;/span&gt;     &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getcwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;'gif'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
   &lt;span class="p"&gt;...:&lt;/span&gt;     &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getcwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;'svg'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
   &lt;span class="p"&gt;...:&lt;/span&gt; &lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;img_lib.lib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AVAILABLE_EXTENSIONS&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'png'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'jpg'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_loaded_mimetypes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'image/png'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'image/jpeg'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AVAILABLE_EXTENSIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;'svg'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'gif'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_modules&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_loaded_mimetypes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'image/png'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'image/jpeg'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'image/svg+xml'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'image/gif'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All the source code of this example is available in &lt;a href="https://github.com/bastantoine/python-namespace-packages-example"&gt;this GitHub repo&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Sources
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.python.org/dev/peps/pep-0420/"&gt;PEP 420 - Implicit Namespace Packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bastien-antoine.fr/2021/10/playing-with-python-path-attribute.md"&gt;Playing with Python &lt;code&gt;__path__&lt;/code&gt; attribute&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;this setup would prevent you to import both modules &lt;code&gt;foo.py&lt;/code&gt; and &lt;code&gt;bar.py&lt;/code&gt; at the same time if both &lt;code&gt;/home/myUser/dev/package&lt;/code&gt; and &lt;code&gt;/var/usr/lib/package&lt;/code&gt; where to be in &lt;code&gt;sys.path&lt;/code&gt; at the same time. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>Http Requests Cheatsheet</title>
      <dc:creator>Bastien ANTOINE</dc:creator>
      <pubDate>Mon, 27 Dec 2021 09:21:09 +0000</pubDate>
      <link>https://dev.to/bastantoine/http-requests-cheatsheet-27me</link>
      <guid>https://dev.to/bastantoine/http-requests-cheatsheet-27me</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: this article was originally published on my personal blog. Check it out &lt;a href="https://bastien-antoine.fr"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When working around APIs, whether it is building or playing with, you often end up making API requests over and over that all look alike, and yet there are some stuff that you can't remember. Like how would you provide form data with cURL? Or basic authentication with &lt;code&gt;requests&lt;/code&gt;? This article serves as a cheatsheet on all those common stuff.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.toselecting-the-http-method"&gt;Selecting the HTTP method&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.toheaders"&gt;Headers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.toauthentication"&gt;Authentication&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.tohttp-basic"&gt;HTTP Basic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.tohttp-bearer"&gt;HTTP Bearer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.toquery-parameters"&gt;Query parameters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.tobody-parameters"&gt;Body parameters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.tosending-files"&gt;Sending files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.todisabling-ssl-verification"&gt;Disabling SSL verification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to3xx-redirects"&gt;3XX redirects&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.tologging"&gt;Logging&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Selecting the HTTP method
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;requests&lt;/code&gt; (Python)
&lt;/h2&gt;

&lt;p&gt;3 possible ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using the &lt;code&gt;requests.request&lt;/code&gt; method:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'https://httpbin.org/get'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'https://httpbin.org/post'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'PUT'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'https://httpbin.org/put'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'PATCH'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'https://httpbin.org/patch'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'DELETE'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'https://httpbin.org/delete'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'HEAD'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'https://httpbin.org/get'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Using the &lt;code&gt;requests.&amp;lt;method&amp;gt;&lt;/code&gt; methods:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'https://httpbin.org/get'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'https://httpbin.org/post'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'https://httpbin.org/put'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'https://httpbin.org/patch'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'https://httpbin.org/delete'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'https://httpbin.org/get'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Using a prepared request:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'https://httpbin.org/get'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From &lt;a href="https://docs.python-requests.org/en/latest/api/#requests.PreparedRequest"&gt;&lt;code&gt;requests.PreparedRequest&lt;/code&gt; documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  cURL
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; GET https://httpbin.org/get
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://httpbin.org/post
curl &lt;span class="nt"&gt;-X&lt;/span&gt; PUT https://httpbin.org/put
curl &lt;span class="nt"&gt;-X&lt;/span&gt; PATCH https://httpbin.org/patch
curl &lt;span class="nt"&gt;-X&lt;/span&gt; DELETE https://httpbin.org/delete
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the &lt;code&gt;-X/--request&lt;/code&gt; is not provided, cURL will default to &lt;code&gt;GET&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://curl.se/docs/manpage.html#-X"&gt;[doc of &lt;code&gt;-X/--request&lt;/code&gt; option]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note on the &lt;code&gt;HEAD&lt;/code&gt; requests&lt;/em&gt;: to make a proper &lt;code&gt;HEAD&lt;/code&gt; request (ie. requesting only the headers), the &lt;code&gt;-X HEAD&lt;/code&gt; option will not work, you will need to use &lt;a href="https://curl.se/docs/manpage.html#-I"&gt;&lt;code&gt;-I/--head&lt;/code&gt;&lt;/a&gt; instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; curl &lt;span class="nt"&gt;-X&lt;/span&gt; HEAD https://httpbin.org/get
Warning: Setting custom HTTP method to HEAD with &lt;span class="nt"&gt;-X&lt;/span&gt;/--request may not work the
Warning: way you want. Consider using &lt;span class="nt"&gt;-I&lt;/span&gt;/--head instead.
curl: &lt;span class="o"&gt;(&lt;/span&gt;18&lt;span class="o"&gt;)&lt;/span&gt; transfer closed with 255 bytes remaining to &lt;span class="nb"&gt;read&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://httpbin.org/get
HTTP/2 200
&lt;span class="nb"&gt;date&lt;/span&gt;: Sun, 19 Dec 2021 11:03:31 GMT
content-type: application/json
content-length: 255
server: gunicorn/19.9.0
access-control-allow-origin: &lt;span class="k"&gt;*&lt;/span&gt;
access-control-allow-credentials: &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Tested on cURL 7.64.0 and 7.77.0)&lt;/p&gt;

&lt;h1&gt;
  
  
  Headers
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;requests&lt;/code&gt; (Python)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;'https://httpbin.org/headers'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;'X-My-Header'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'Value'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://2.python-requests.org/en/master/user/quickstart/#custom-headers"&gt;[doc of &lt;code&gt;headers&lt;/code&gt; parameter]&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  cURL
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'X-My-Header: Value'&lt;/span&gt; https://httpbin.org/headers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://curl.se/docs/manpage.html#-H"&gt;[doc of &lt;code&gt;-H/--headers&lt;/code&gt; option]&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Authentication
&lt;/h1&gt;

&lt;h2&gt;
  
  
  HTTP Basic
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;requests&lt;/code&gt; (Python)
&lt;/h3&gt;

&lt;p&gt;2 possible ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using the &lt;a href="https://2.python-requests.org/en/master/user/authentication/#basic-authentication"&gt;&lt;code&gt;auth&lt;/code&gt;&lt;/a&gt; option
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;'https://httpbin.org/basic-auth/user/passwd'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'passwd'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Using the &lt;a href="https://docs.python-requests.org/en/latest/user/quickstart/#custom-headers"&gt;headers&lt;/a&gt; option
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;'https://httpbin.org/basic-auth/user/passwd'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;'Authorization'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'Basic dXNlcjpwYXNzd2QK'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;base64&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;b64encode&lt;/span&gt;
&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;'https://httpbin.org/basic-auth/user/passwd'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;'Authorization'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;'Basic &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;b64encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'user:passwd'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note on using this along with a &lt;code&gt;.netrc&lt;/code&gt; file&lt;/em&gt;: Authorization headers that are provided this way will be overriden by credentials set in the &lt;code&gt;.netrc&lt;/code&gt; file &lt;a href="https://2.python-requests.org/en/master/user/authentication/#netrc-authentication"&gt;[doc]&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As a workaround you can either temporarily comment the authentication part in your &lt;code&gt;.netrc&lt;/code&gt;, set the &lt;code&gt;NETRC&lt;/code&gt; env var to an empty file, or temporarily set &lt;code&gt;requests.utils.NETRC_FILES = []&lt;/code&gt; &lt;a href="https://github.com/psf/requests/blob/2d2447e210cf0b9e8c7484bfc6f158de9b24c171/requests/utils.py#L178"&gt;[source code]&lt;/a&gt; .&lt;/p&gt;

&lt;h3&gt;
  
  
  cURL
&lt;/h3&gt;

&lt;p&gt;2 possible ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using the &lt;a href="https://curl.se/docs/manpage.html#-u"&gt;&lt;code&gt;-u/--user&lt;/code&gt;&lt;/a&gt; option
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-u&lt;/span&gt; user:passwd https://httpbin.org/basic-auth/user/passwd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Few things to note when using this option:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cURL will split the username and password on the first colon. This means you can't have one in the username, but you can in the password. If needed, use the solution below with the &lt;code&gt;-H/--header&lt;/code&gt; option.&lt;/li&gt;
&lt;li&gt;If only the username is provided, cURL will prompt for the password before sending the request&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Using the &lt;a href="https://curl.se/docs/manpage.html#-H"&gt;&lt;code&gt;-H/--header&lt;/code&gt;&lt;/a&gt; option
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Basic dXNlcjpwYXNzd2QK'&lt;/span&gt; https://httpbin.org/basic-auth/user/passwd
curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Basic &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;openssl &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; user:passwd&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; https://httpbin.org/basic-auth/user/passwd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  HTTP Bearer
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;requests&lt;/code&gt; (Python)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;'https://httpbin.org/bearer'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;'Authorization'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'Basic dGhpc0lzQUJlYXJlclRva2VuCg=='&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  cURL
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer dGhpc0lzQUJlYXJlclRva2VuCg=='&lt;/span&gt; https://httpbin.org/bearer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Query parameters
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;requests&lt;/code&gt; (Python)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;'https://httpbin.org/anything'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s"&gt;'arg1'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'val1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;'arg2'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'val2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://2.python-requests.org/en/master/user/quickstart/#passing-parameters-in-urls"&gt;[doc of &lt;code&gt;params&lt;/code&gt; parameter]&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  cURL
&lt;/h2&gt;

&lt;p&gt;No useful options here unfortunately&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://httpbin.org/anything?arg1&lt;span class="o"&gt;=&lt;/span&gt;val1&amp;amp;arg2&lt;span class="o"&gt;=&lt;/span&gt;val2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Body parameters
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;requests&lt;/code&gt; (Python)
&lt;/h2&gt;

&lt;p&gt;There are multiple ways to provide a body, each with their side consequences:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Providing a dict in the &lt;code&gt;data&lt;/code&gt; parameter: this will set the &lt;code&gt;Content-Type&lt;/code&gt; header to &lt;code&gt;application/x-www-form-urlencoded&lt;/code&gt;, unless told otherwise by the &lt;code&gt;headers&lt;/code&gt; parameter.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;"https://httpbin.org/post"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'key1'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'value1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'key2'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'value2'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Providing a raw string in the &lt;code&gt;data&lt;/code&gt; parameter: this will not set any value to the &lt;code&gt;Content-Type&lt;/code&gt; header.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;"https://httpbin.org/post"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'theBodyOfMyRequest'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Providing a dict in the &lt;code&gt;json&lt;/code&gt; parameter: this will dumps the provided payload as JSON and set the &lt;code&gt;Content-Type&lt;/code&gt; header to &lt;code&gt;application/json&lt;/code&gt;, unless told otherwise by the &lt;code&gt;headers&lt;/code&gt; parameter. The following two request are equivalents:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;"https://httpbin.org/post"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s"&gt;'key1'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'value1 and value2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'key2'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'value2'&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'Content-Type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'application/json'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;"https://httpbin.org/post"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'key1'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'value1 and value2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'key2'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'value2'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://docs.python-requests.org/en/latest/user/quickstart/#more-complicated-post-requests"&gt;[doc]&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  cURL
&lt;/h2&gt;

&lt;p&gt;cURL offers multiple options to send a request with a body, each with their side consequences as well.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using the &lt;code&gt;-F/--form&lt;/code&gt; option
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="nv"&gt;key1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;value1 &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="nv"&gt;key2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;value2 https://httpbin.org/post
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Few things to note when using this option:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it forces the method to &lt;code&gt;POST&lt;/code&gt;, unless told otherwise with &lt;code&gt;-X/--request&lt;/code&gt; option&lt;/li&gt;
&lt;li&gt;it sets the &lt;code&gt;Content-Type&lt;/code&gt; header to &lt;code&gt;multipart/form-data&lt;/code&gt;, unless told otherwise aswell with &lt;code&gt;-H/--header&lt;/code&gt; option&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using this option, it is possible to send files or read input from a file by prefixing the filename with &lt;code&gt;@&lt;/code&gt; or &lt;code&gt;&amp;lt;&lt;/code&gt;, respectively. This means that if you need to have either a &lt;code&gt;@&lt;/code&gt; or &lt;code&gt;&amp;lt;&lt;/code&gt; in the key and/or the value, you need to use the &lt;code&gt;--form-string&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://curl.se/docs/manpage.html#-F"&gt;[doc of &lt;code&gt;-F/--form&lt;/code&gt; option]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://curl.se/docs/manpage.html#--form-string"&gt;[doc of &lt;code&gt;--form-string&lt;/code&gt; option]&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using &lt;code&gt;-d/--data&lt;/code&gt; option
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nv"&gt;key1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;value1 &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nv"&gt;key2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;value2 https://httpbin.org/post
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Few things to note when using this option:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it forces the method to &lt;code&gt;POST&lt;/code&gt;, unless told otherwise with &lt;code&gt;-X/--request&lt;/code&gt; option&lt;/li&gt;
&lt;li&gt;it sets the &lt;code&gt;Content-Type&lt;/code&gt; header to &lt;code&gt;application/x-www-form-urlencoded&lt;/code&gt;, unless told otherwise aswell with &lt;code&gt;-H/--header&lt;/code&gt; option&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using this option, it is possible to read input from a file by prefixing the filename with &lt;code&gt;@&lt;/code&gt;. This means that if you need to have a &lt;code&gt;@&lt;/code&gt; in the key and/or the value you need to use the &lt;code&gt;--data-raw&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;It is also possible to URL-encode the parameter using the &lt;code&gt;--data-urlencode&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://curl.se/docs/manpage.html#-d"&gt;[doc of &lt;code&gt;-d/--data&lt;/code&gt; option]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://curl.se/docs/manpage.html#--data-raw"&gt;[doc of &lt;code&gt;--data-raw&lt;/code&gt; option]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://curl.se/docs/manpage.html#--data-urlencode"&gt;[doc of &lt;code&gt;--data-urlencode&lt;/code&gt; option]&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Sending files
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;requests&lt;/code&gt; (Python)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;'https://httpbin.org/post'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'file'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'index.html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'index.html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'rb'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;'text/html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'Expires'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'0'&lt;/span&gt;&lt;span class="p"&gt;})}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://docs.python-requests.org/en/latest/user/quickstart/#post-a-multipart-encoded-file"&gt;[doc]&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  cURL
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s2"&gt;"file=@index.html"&lt;/span&gt; https://httpbin.org/post
curl &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s2"&gt;"file=@index.html;type=text/html"&lt;/span&gt; https://httpbin.org/post
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://curl.se/docs/manpage.html#-F"&gt;[doc of &lt;code&gt;-F/--form&lt;/code&gt; option]&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Disabling SSL verification
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;requests&lt;/code&gt; (Python)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;'https://httpbin.org/get'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;verify&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://2.python-requests.org/en/master/api/#requests.Session.verify"&gt;[doc of &lt;code&gt;verify&lt;/code&gt; parameter]&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  cURL
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-k&lt;/span&gt; https://httpbin.org/get
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://curl.se/docs/manpage.html#-k"&gt;[doc of &lt;code&gt;-k/--insecure&lt;/code&gt; option]&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  3XX redirects
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;requests&lt;/code&gt; (Python)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;requests&lt;/code&gt; default behavior is to follow redirect, unless making a &lt;code&gt;HEAD&lt;/code&gt; request (see below for more informations). Use the parameter &lt;code&gt;allow_redirects&lt;/code&gt; to disable it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;'https://httpbin.org/redirect-to?url=bastien-antoine.fr&amp;amp;status_code=302'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;allow_redirects&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note on redirects with HEAD requests&lt;/em&gt;: when making &lt;code&gt;HEAD&lt;/code&gt; requests, &lt;code&gt;requests&lt;/code&gt; will not follow 3XX redirects in most case, depending on how the request is made:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;How the request is made&lt;/th&gt;
&lt;th&gt;Follow 3XX on default&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://dev.torequests-head-source-code"&gt;&lt;code&gt;requests.head(...)&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/psf/requests/blob/b0e025ade7ed30ed53ab61f542779af7e024932e/requests/sessions.py#L568"&gt;&lt;code&gt;requests.Session(...).head(...)&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/psf/requests/blob/b0e025ade7ed30ed53ab61f542779af7e024932e/requests/sessions.py#L470"&gt;&lt;code&gt;requests.request('HEAD', ...)&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  cURL
&lt;/h2&gt;

&lt;p&gt;cURL's default behavior is to not follow 3XX redirects. To enable this use the &lt;code&gt;-L/--location&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-L&lt;/span&gt; https://httpbin.org/redirect-to?url&lt;span class="o"&gt;=&lt;/span&gt;bastien-antoine.fr&amp;amp;status_code&lt;span class="o"&gt;=&lt;/span&gt;302
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://curl.se/docs/manpage.html#-L"&gt;[doc of &lt;code&gt;-L/--location&lt;/code&gt; option]&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Logging
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;requests&lt;/code&gt; (Python)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;http.client&lt;/span&gt;

&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTPConnection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debuglevel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;setLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;requests_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"requests.packages.urllib3"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;requests_log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;requests_log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;propagate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://stackoverflow.com/a/26460395"&gt;[source]&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  cURL
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; https://httpbin.org/get
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that this option only shows requests headers and full response. If you want to see the whole process, including request body, checkout the &lt;a href="https://curl.se/docs/manpage.html#--trace"&gt;&lt;code&gt;--trace&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://curl.se/docs/manpage.html#--trace-ascii"&gt;&lt;code&gt;--trace-ascii&lt;/code&gt;&lt;/a&gt; options.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://curl.se/docs/manpage.html#-v"&gt;[doc of &lt;code&gt;-v/--verbose&lt;/code&gt; option]&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cheatsheet</category>
      <category>httprequests</category>
    </item>
    <item>
      <title>Quick intro to Bash I/O redirections, *here documents* and *here strings*</title>
      <dc:creator>Bastien ANTOINE</dc:creator>
      <pubDate>Mon, 27 Dec 2021 09:20:44 +0000</pubDate>
      <link>https://dev.to/bastantoine/quick-intro-to-bash-io-redirections-here-documents-and-here-strings-36d2</link>
      <guid>https://dev.to/bastantoine/quick-intro-to-bash-io-redirections-here-documents-and-here-strings-36d2</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: this article was originally published on my personal blog. Check it out &lt;a href="https://bastien-antoine.fr"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you have done a bit of scripting in Bash, you may know that you can redirect the input and output of the commands to other commands or files. This article introduces the basic of I/O redirections and explains some of the syntax that may seems cryptic at first.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.tostdin-stdout-and-stderr"&gt;&lt;code&gt;stdin&lt;/code&gt;, &lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stderr&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.tocontrolling-the-program-input-and-output"&gt;Controlling the program input and output&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.tocontrolling-the-input"&gt;Controlling the input&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.tohere-documents-and-here-strings"&gt;&lt;em&gt;Here documents&lt;/em&gt; and &lt;em&gt;here strings&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.tocontrolling-the-output"&gt;Controlling the output&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.tocontrolling-stdout"&gt;Controlling &lt;code&gt;stdout&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.tocontrolling-stderr"&gt;Controlling &lt;code&gt;stderr&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.toa-note-on-the-pipe-operator"&gt;A note on the pipe operator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  &lt;code&gt;stdin&lt;/code&gt;, &lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stderr&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;In Bash every command or script has three files&lt;sup id="fnref1"&gt;1&lt;/sup&gt; opened when running:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;stdin&lt;/code&gt; (&lt;em&gt;STanDart INput&lt;/em&gt;): the input of the data fed to the program&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;stdout&lt;/code&gt; (&lt;em&gt;STanDart OUTput&lt;/em&gt;): the location where the program will output anything it needs to output&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;stderr&lt;/code&gt; (&lt;em&gt;STanDart ERRor&lt;/em&gt;): the location where the program will output any error occured during the run&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each of them get assigned to a specific &lt;em&gt;file descriptor&lt;/em&gt; (ie. a number assigned to the file used by the OS to handle it): O for &lt;code&gt;stdin&lt;/code&gt;, 1 for &lt;code&gt;stdout&lt;/code&gt; and 2 for &lt;code&gt;stderr&lt;/code&gt;. These numbers allow you to control and use them in your program.&lt;/p&gt;

&lt;h1&gt;
  
  
  Controlling the program input and output
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Controlling the input
&lt;/h2&gt;

&lt;p&gt;Depending on the programm that you want to run, there might be different ways to control on their input is provided: some are built to accept files, some will read only from &lt;code&gt;stdin&lt;/code&gt; and others may accept both.&lt;/p&gt;

&lt;p&gt;When it comes to directly providing files to the program, I'll let you read their manpage to know how to do so.&lt;/p&gt;

&lt;p&gt;When your program is launched directly in a terminal, its &lt;code&gt;stdin&lt;/code&gt; is attached to your keyboard, providind you with a way to input the data.&lt;/p&gt;

&lt;p&gt;If you want to use something else as the input, there are a few ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using the &lt;code&gt;&amp;lt;&lt;/code&gt; operator: this operator allows to use the content of a file as the input data stream.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;input-file &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
Line 8
Line 9
Line 10
Line 11
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"^Line 1"&lt;/span&gt; &amp;lt;input-file
Line 1
Line 10
Line 11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(See section below about &lt;em&gt;here docs&lt;/em&gt; to understand the syntax of the first command.)&lt;/p&gt;

&lt;p&gt;You can also use the &lt;code&gt;0&amp;lt;&lt;/code&gt; operator, which is equivalent to &lt;code&gt;&amp;lt;&lt;/code&gt;. The 0 here is a reference to the file descriptor 0 attached to &lt;code&gt;stdin&lt;/code&gt;, but because a program only has one &lt;code&gt;stdout&lt;/code&gt;, it can be abreviated from &lt;code&gt;0&amp;lt;&lt;/code&gt; to &lt;code&gt;&amp;lt;&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Using the pipe &lt;code&gt;|&lt;/code&gt; operator: the pipe operator is a special operator that combines input and output redirection to allow chaining commands. See below for more info.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using &lt;em&gt;here documents&lt;/em&gt; and &lt;em&gt;here strings&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Here documents&lt;/em&gt; and &lt;em&gt;here strings&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Here documents&lt;/em&gt; (or &lt;em&gt;heredoc&lt;/em&gt;) are a special form of input redirection allowing to input a multiline string to a program. The syntax is the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;COMMAND &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;DELIMITOR&lt;/span&gt;&lt;span class="sh"&gt;
...
...
&lt;/span&gt;&lt;span class="no"&gt;DELIMITOR
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;DELIMITOR&lt;/code&gt; is used to control when to start and stop the input. It can be any string without spaces, and should then be choosed wiselly so that it won't apear in the input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;ThisIsADelimitor&lt;/span&gt;&lt;span class="sh"&gt;
Hello
There
&lt;/span&gt;&lt;span class="no"&gt;ThisIsADelimitor
&lt;/span&gt;Hello
There
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;
Hello
There
&lt;/span&gt;&lt;span class="no"&gt;1
&lt;/span&gt;Hello
There
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Heredoc&lt;/em&gt; allows for parameter expansion as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FIRSTNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Obi-Wan'&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LASTNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Kenobi'&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
Hello &lt;/span&gt;&lt;span class="nv"&gt;$FIRSTNAME&lt;/span&gt;&lt;span class="sh"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$LASTNAME&lt;/span&gt;&lt;span class="sh"&gt;
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;Hello Obi-Wan Kenobi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have played a bit with the &lt;em&gt;heredocs&lt;/em&gt;, you may have noticed that tabs included in the input were kept:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
        hello
there
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;    hello
there
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fortunately you can strip them by prefixing the delimitor with a dash:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
        hello
there
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;hello
there
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will strip all leading tabs, allowing the input to be more readable visually. Note though that this strips only leading tabs, not spaces, so be careful, especially if you copy/paste the example above.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;Here strings&lt;/em&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Here strings&lt;/em&gt; are a more consise version of the &lt;em&gt;here documents&lt;/em&gt;. They only allow a single line input, and thus don't need the use of a string delimitor. Like the &lt;em&gt;heredocs&lt;/em&gt;, it allows for parameter expansion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt; &amp;gt; file
This is
a
multiline
file
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TITLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Title of the file"&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"file"&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; - &lt;span class="nv"&gt;$FILE&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;$TITLE&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$FILE&lt;/span&gt;.new
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nv"&gt;$FILE&lt;/span&gt;.new
Title of the file
This is
a
multiline
file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Controlling the output
&lt;/h2&gt;

&lt;p&gt;Like for the input, there are a few ways to redirect the output of a program, but unlike the first, a program has two type of possible outputs, &lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stderr&lt;/code&gt;, so there are ways to control which output gets redirected.&lt;/p&gt;

&lt;p&gt;When the program is launched directly in a terminal, its &lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stderr&lt;/code&gt; are attached to the terminal, so everything the program outputs gets printed on your screen.&lt;/p&gt;

&lt;h3&gt;
  
  
  Controlling &lt;code&gt;stdout&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Using the &lt;code&gt;&amp;gt;&lt;/code&gt; operator: redirects &lt;code&gt;stdout&lt;/code&gt; to the provided filename, creates it if needed, otherwise overwrite it.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; list-files.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Using the &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; operator: same as &lt;code&gt;&amp;gt;&lt;/code&gt;, but appends to the end of the file if it already exists
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-lat&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n3&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; most-recents-files.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Controlling &lt;code&gt;stderr&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Using the &lt;code&gt;2&amp;gt;&lt;/code&gt; operator: same as &lt;code&gt;&amp;gt;&lt;/code&gt; for &lt;code&gt;stdout&lt;/code&gt;, but for &lt;code&gt;stderr&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ERRORFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;script.errors
&lt;span class="nv"&gt;$ &lt;/span&gt;bad_command1 2&amp;gt;&lt;span class="nv"&gt;$ERRORFILE&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nv"&gt;$ERRORFILE&lt;/span&gt;
zsh: &lt;span class="nb"&gt;command &lt;/span&gt;not found: bad_command1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Using the &lt;code&gt;2&amp;gt;&amp;gt;&lt;/code&gt; operator: same as &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; for &lt;code&gt;stdout&lt;/code&gt;, but for &lt;code&gt;stderr&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ERRORFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;script.errors
&lt;span class="nv"&gt;$ &lt;/span&gt;bad_command1 2&amp;gt;&amp;gt;&lt;span class="nv"&gt;$ERRORFILE&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nv"&gt;$ERRORFILE&lt;/span&gt;
zsh: &lt;span class="nb"&gt;command &lt;/span&gt;not found: bad_command1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;2&amp;gt;&amp;amp;1&lt;/code&gt;: redirects &lt;code&gt;stderr&lt;/code&gt; to &lt;code&gt;stdout&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;&amp;amp;&amp;gt; filename&lt;/code&gt;: redirects both &lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stderr&lt;/code&gt; to &lt;code&gt;filename&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  A note on the pipe operator
&lt;/h3&gt;

&lt;p&gt;The pipe operator &lt;code&gt;|&lt;/code&gt; is special operator that allows to chain multiple commands by binding the &lt;code&gt;stdout&lt;/code&gt; of one to the &lt;code&gt;stdin&lt;/code&gt; of the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example above would be roughly the same as the following script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nv"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;temp
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;$filename&lt;/span&gt;
&lt;span class="nb"&gt;exec &lt;/span&gt;3&amp;lt;&lt;span class="nv"&gt;$filename&lt;/span&gt;
&lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; &amp;lt;&amp;amp;3
3&amp;lt;&amp;amp;-
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; &lt;span class="nv"&gt;$filename&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Sources
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tldp.org/LDP/abs/html/io-redirection.html#IOREDIRREF"&gt;&lt;em&gt;Advanced Bash-Scripting Guide: Chapter 20. I/O Redirection&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tldp.org/LDP/abs/html/here-docs.html"&gt;&lt;em&gt;Advanced Bash-Scripting Guide: Chapter 19. Here Documents&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tldp.org/LDP/abs/html/x17837.html"&gt;&lt;em&gt;Advanced Bash-Scripting Guide: Chapter 19.1. Here Strings&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;While they may use regular files as input or output these are actually more like data streams, but by convention the UNIX and Linux world treat them like files. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>Playing with Python `__path__` attribute</title>
      <dc:creator>Bastien ANTOINE</dc:creator>
      <pubDate>Thu, 23 Dec 2021 17:17:42 +0000</pubDate>
      <link>https://dev.to/bastantoine/playing-with-python-path-attribute-3ic3</link>
      <guid>https://dev.to/bastantoine/playing-with-python-path-attribute-3ic3</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: this article was originally published on my personal blog. Check it out &lt;a href="https://bastien-antoine.fr"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Recently, when preparing an article about Python import system, I discovered the &lt;a href="https://docs.python.org/3/reference/import.html#module-path"&gt;&lt;code&gt;__path__&lt;/code&gt;&lt;/a&gt; attribute and found some cool stuff to do with it, so I wanted to show what I discovered.&lt;/p&gt;

&lt;p&gt;Take a look at the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;myPackage/
├── __init__.py
├── subPackageA/
│   ├── __init__.py
│   └── foo.py       # Has a function foo()
└── subPackageB/
    ├── __init__.py
    └── bar.py       # Has a function bar()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First case: all the &lt;code&gt;__init__.py&lt;/code&gt; files of the package and subpackages are empty (that's important, we'll get to that later).&lt;/p&gt;

&lt;p&gt;In this case, if we want to import the functions &lt;code&gt;foo&lt;/code&gt; and &lt;code&gt;bar&lt;/code&gt; from their modules &lt;code&gt;foo&lt;/code&gt; and &lt;code&gt;bar&lt;/code&gt;, we would have to do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;myPackage.subPackageA.foo&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;myPackage.subPackageB.bar&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing new here.&lt;/p&gt;

&lt;p&gt;Now second case, we update &lt;code&gt;myPackage/subPackageA/__init__.py&lt;/code&gt; and put this little piece of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;

&lt;span class="n"&gt;current_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;realpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;__path__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abspath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'..'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="s"&gt;'subPackageB'&lt;/span&gt;
&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that in place we can do some magic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;myPackage.subPackageA.foo&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;myPackage.subPackageA.bar&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we imported &lt;code&gt;bar&lt;/code&gt; from &lt;code&gt;subPackageA&lt;/code&gt;, but &lt;code&gt;bar.py&lt;/code&gt; is still under &lt;code&gt;myPackage/subPackageB&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;myPackage.subPackageA&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;
&lt;span class="s"&gt;'&amp;lt;...&amp;gt;/myPackage/subPackageB/bar.py'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what happened here? Why were we able to import &lt;code&gt;bar&lt;/code&gt; under &lt;code&gt;subPackageA&lt;/code&gt;'s namespace just by adding a piece of code inside &lt;code&gt;myPackage/subPackageA/__init__.py&lt;/code&gt;? Time for some explanations.&lt;/p&gt;

&lt;h1&gt;
  
  
  The &lt;code&gt;__init__.py&lt;/code&gt; file and the usage of the &lt;code&gt;__path__&lt;/code&gt; attribute
&lt;/h1&gt;

&lt;p&gt;The &lt;code&gt;__init__.py&lt;/code&gt; file is a special file that indicate that the current folder is a Python package. During the import process, when Python finds the source of a module or package it is asked to import, it will read and execute all the &lt;code&gt;__init__.py&lt;/code&gt; files of the package and subpackages of the module.&lt;/p&gt;

&lt;p&gt;So take the following structure. Each of the &lt;code&gt;__init__.py&lt;/code&gt; file has a simple &lt;code&gt;print(__name__)&lt;/code&gt; so that we can see what's going on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;packageA/
├── __init__.py
└── packageB/
    ├── __init__.py
    └── packageC/
        ├── __init__.py
        └── packageD/
            ├── __init__.py
            └── module.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And when we try to import the module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;packageA.packageB.packageC.packageD&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;
&lt;span class="n"&gt;packageA&lt;/span&gt;
&lt;span class="n"&gt;packageA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;packageB&lt;/span&gt;
&lt;span class="n"&gt;packageA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;packageB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;packageC&lt;/span&gt;
&lt;span class="n"&gt;packageA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;packageB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;packageC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;packageD&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So in our example above, the code we added in &lt;code&gt;subPackageA/__init__.py&lt;/code&gt; we executed when Python executed &lt;code&gt;from myPackage.subPackageA.foo import foo&lt;/code&gt;. This piece of code look perhaps a bit cryptic, but it simply does one thing: add the absolute path to &lt;code&gt;myPackage/subPackageB/&lt;/code&gt; to the &lt;code&gt;__path__&lt;/code&gt; of &lt;code&gt;subPackageA&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;__path__&lt;/code&gt; attribute of a Python package is used by the import system when trying to import modules of subpackages. It is a list (or at least an iterable) of paths that can be used when importing modules or subpackages.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;django&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__path__&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'&amp;lt;...&amp;gt;/venv/lib/python3.9/site-packages/django'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;django.db&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;
&lt;span class="s"&gt;'&amp;lt;...&amp;gt;/venv/lib/python3.9/site-packages/django/db/__init__.py'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So when we updated &lt;code&gt;subPackageA.__path__&lt;/code&gt; to add &lt;code&gt;subPackageB&lt;/code&gt;, we told Python to bind the objects of &lt;code&gt;subPackageB/&lt;/code&gt; under the namespace of &lt;code&gt;subPackageA&lt;/code&gt;, which is why we were able to import &lt;code&gt;bar&lt;/code&gt; from &lt;code&gt;subPackageA&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Two points to note though:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The update of &lt;code&gt;subPackageA.__path__&lt;/code&gt; can be done even if the &lt;code&gt;__path__&lt;/code&gt; has not been updated with the new path yet. I believe this is because when Python tries to resolve the paths of the imports, it executes all the &lt;code&gt;__init__.py&lt;/code&gt; files it finds in paths that matches (even partially) the import required. I still needs confirme this though.&lt;/li&gt;
&lt;li&gt;It is still possible to import the objects of &lt;code&gt;subPackageB&lt;/code&gt; under its own namespace.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Possible usage of this trick
&lt;/h1&gt;

&lt;p&gt;Now that you know this is possible, you may be wondering what could be a possible real-life use of this.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;__path__&lt;/code&gt; can be used sometimes when you're dealing with dynamic imports. For example Django uses them when dealing with modules provided by the user.&lt;/p&gt;

&lt;p&gt;Another possibility is to hide the internal structure of a package. If you can dynamically choose which namespace to bind your objects to, you can basically choose the structure you want for your package, no matter the internal organizations of files and folders. Note that this usage is probably just theoretical, as it wouldn't be really useful in real life. I see a few reason for this limitation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Like I said before, the dynamic binding of objects to a namespace other than their own doesn't prevent them to be imported via their own namespace (cf. point 2. above).&lt;/li&gt;
&lt;li&gt;When a package is installed into the &lt;code&gt;site-packages&lt;/code&gt; folder (whether system-wide or in a virtualenv), it is possible to see the source files of it, so people would still be able to figure out how the package is structured internally.&lt;/li&gt;
&lt;li&gt;If you really want to acheive this, it might be easier to add imports to the &lt;code&gt;__init__.py&lt;/code&gt; files, as they are executed when the package is imported, than to mess with &lt;code&gt;__path__&lt;/code&gt; attribute.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A last possibility is to be able to extend packages via some extensions that can be installed separately, and registered to the main package, to make their usage as transparent as possible. Let's take an example to make things a bit easier to understand.&lt;/p&gt;

&lt;p&gt;Let's say you create a package &lt;code&gt;imageLib&lt;/code&gt; to handle image manipulation. You have functions to resize, crop, rotate... All this functions needs to have an image decoded (ie. a matrix of pixels) to work, so you need to provide functions for encoding and decoding each common image format (png, jpg, gif...). But you don't want to include all the extensions into your lib, so that people will have to download and install only those they need.&lt;/p&gt;

&lt;p&gt;That's where &lt;code&gt;__path__&lt;/code&gt; manipulation comes handy. The extensions can have a &lt;code&gt;.register()&lt;/code&gt; function that will find the &lt;code&gt;__path__&lt;/code&gt; attribute of the lib (or any of it's subpackage), and add themselves to it, so that the import can be as smooth as possible.&lt;/p&gt;

&lt;p&gt;Turns out this ability is something that is quite popular, named &lt;strong&gt;namespace packages&lt;/strong&gt;. This was a functionnality available using the &lt;code&gt;pkgutil&lt;/code&gt; package, but it's part of Python since Python 3.3 (Sept. 2012) with &lt;a href="https://www.python.org/dev/peps/pep-0420"&gt;PEP 420&lt;/a&gt;. This PEP is really interesting, but that'll be for another article.&lt;/p&gt;

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