<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Björn Ricks - python</title><link href="https://bjoernricks.github.io/" rel="alternate"/><link href="/feeds/python.atom.xml" rel="self"/><id>https://bjoernricks.github.io/</id><updated>2024-03-04T10:00:00+00:00</updated><subtitle>A personal Blog.</subtitle><entry><title>Understanding Context Manager and its Syntastic Sugar</title><link href="https://bjoernricks.github.io/posts/python/context-manager/" rel="alternate"/><published>2024-03-04T10:00:00+00:00</published><updated>2024-03-04T10:00:00+00:00</updated><author><name>Björn Ricks</name></author><id>tag:bjoernricks.github.io,2024-03-04:/posts/python/context-manager/</id><summary type="html">&lt;p&gt;The Context Manager is one of my favorite features in Python. It can be used for
all kind of interesting things around blocks of code. This article gives a
background about the origins of the context manager, which problem it solves and
how to use it.&lt;/p&gt;
&lt;nav&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#origins"&gt;Origins &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#context-manager-protocol"&gt;Context Manager Protocol &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#the-with-statement-as-syntastic-sugar"&gt;The With Statement as Syntastic Sugar &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#implementing-a-context-manager-using-contextlib"&gt;Implementing a Context Manager using contextlib &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#capture-the-call-flow"&gt;Capture the Call Flow &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#example-context-managers"&gt;Example Context Managers &lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#example-1---redirect-stdout"&gt;Example 1 - Redirect Stdout &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#example-2---suppress-exceptions"&gt;Example 2 - Suppress Exceptions &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#example-3---add-a-directory-to-the-python-module-search-path-temporarily"&gt;Example 3 - Add a directory to the Python module search path temporarily &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#example-4---print-prefix"&gt;Example 4 - Print Prefix &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#links"&gt;Links &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/nav&gt;
&lt;a class="button is-link" href="posts/python/context-manager/"&gt;Read more &lt;span class="icon is-small"&gt;&lt;i class="fa fa-angle-double-right"&gt;&lt;/i&gt;&lt;/span&gt;&lt;/a&gt;</summary><content type="html">&lt;p&gt;The Context Manager is one of my favorite features in Python. It can be used for
all kind of interesting things around blocks of code. This article gives a
background about the origins of the context manager, which problem it solves and
how to use it.&lt;/p&gt;
&lt;nav&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#origins"&gt;Origins &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#context-manager-protocol"&gt;Context Manager Protocol &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#the-with-statement-as-syntastic-sugar"&gt;The With Statement as Syntastic Sugar &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#implementing-a-context-manager-using-contextlib"&gt;Implementing a Context Manager using contextlib &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#capture-the-call-flow"&gt;Capture the Call Flow &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#example-context-managers"&gt;Example Context Managers &lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#example-1---redirect-stdout"&gt;Example 1 - Redirect Stdout &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#example-2---suppress-exceptions"&gt;Example 2 - Suppress Exceptions &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#example-3---add-a-directory-to-the-python-module-search-path-temporarily"&gt;Example 3 - Add a directory to the Python module search path temporarily &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#example-4---print-prefix"&gt;Example 4 - Print Prefix &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#links"&gt;Links &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/nav&gt;
&lt;!-- TEASER_END --&gt;
&lt;h1 id="origins"&gt;Origins &lt;a class="header-anchor" href="#origins"&gt;¶&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;When using resources like files, memory, network connections, it is
desirable to release the resources after they aren’t in use anymore. Otherwise
it can cause several issues like not being able to create another connection or
various &lt;a href="https://en.wikipedia.org/wiki/Memory_leak"&gt;memory leaks&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Of course this could be avoided by using &lt;em&gt;opening&lt;/em&gt; and &lt;em&gt;closing&lt;/em&gt; methods (or
functions) on the resources, like in the following code examples:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Example 1 - A network connection&lt;/span&gt;

&lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# use the connection, for example send bytes&lt;/span&gt;
&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Example 2 - A file for I/O&lt;/span&gt;

&lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;foo.txt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# do something with the file, for example read and write bytes&lt;/span&gt;
&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Example 3 - A lock for concurrent access&lt;/span&gt;

&lt;span class="n"&gt;lock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;acquire_lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# run code that requires exclusive access&lt;/span&gt;
&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Example 3 -  Database access&lt;/span&gt;

&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;database_open&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# execute SQL statements for example db.execute(&amp;quot;INSERT INTO foo VALUES (&amp;#39;bar&amp;#39;)&amp;quot;)&lt;/span&gt;
&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But using &lt;em&gt;opening&lt;/em&gt; and &lt;em&gt;closing&lt;/em&gt; methods has some drawbacks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The releasing method may be called conditionally at different places. As a
result the resource may not be closed in all required cases&lt;/li&gt;
&lt;li&gt;The releasing method might never be called because it is just forgotten, the
documentation wasn’t read, …&lt;/li&gt;
&lt;li&gt;At best the method names are standardized (for example to always
to use &lt;code&gt;open&lt;/code&gt; and &lt;code&gt;close&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Errors may occur and exceptions will be raised before the resources can
released&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Especially the last item would always require to write code such as:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;foo.txt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# do something with the file&lt;/span&gt;
&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;where &lt;em&gt;do something with the file&lt;/em&gt; can be very long, contain function calls,
conditionals, additional error handling with nested try/except blocks and
therefore it becomes difficult to read.&lt;/p&gt;
&lt;p&gt;But at the end, this approach is always error prone because it’s just implicitly
required to be run within a try/except block.&lt;/p&gt;
&lt;p&gt;To address these shortcomings, &lt;a href="https://peps.python.org/pep-0343/"&gt;PEP 343&lt;/a&gt;
introduced the &lt;code&gt;with&lt;/code&gt; statement and the &lt;em&gt;Context Manager Protocol&lt;/em&gt;.&lt;/p&gt;
&lt;h1 id="context-manager-protocol"&gt;Context Manager Protocol &lt;a class="header-anchor" href="#context-manager-protocol"&gt;¶&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;As you have seen in the previous examples handling resources always consists of
two phases:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;acquiring&lt;/strong&gt; (or opening)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;releasing&lt;/strong&gt; (or closing)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Context Managers have been introduced to handle the process of acquiring and
releasing of resources automatically even under error conditions.&lt;/p&gt;
&lt;p&gt;Let us take a look at the Context Manager:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;ContextManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__enter__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&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;Any&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Setup and acquire the resource and return it&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__exit__&lt;/span&gt;&lt;span class="p"&gt;(&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;exc_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exc_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;traceback&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;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;        Shutdown and release the resource even if an error was raised&lt;/span&gt;
&lt;span class="sd"&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A context manager implementation consists of two &lt;a href="https://www.pythonmorsels.com/what-are-dunder-methods/"&gt;dunder&lt;/a&gt;
methods, &lt;code&gt;__enter__&lt;/code&gt; and &lt;code&gt;__exit__&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;__enter__&lt;/code&gt; method is intended to setup and acquire a resource. The resource
object or an object handling the resource may be returned from the method
optionally.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;__exit__&lt;/code&gt; method is intended to shutdown and release the resource and gets
the current error information passed if an error was raised. Otherwise the three
arguments are &lt;code&gt;None&lt;/code&gt;. Therefore the method is even able to handle raised errors
optionally. If the error should be suppressed &lt;code&gt;True&lt;/code&gt; must be returned.&lt;/p&gt;
&lt;h1 id="the-with-statement-as-syntastic-sugar"&gt;The With Statement as Syntastic Sugar &lt;a class="header-anchor" href="#the-with-statement-as-syntastic-sugar"&gt;¶&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;To actually execute both methods Context Managers are used in conjunction with
the &lt;code&gt;with&lt;/code&gt; statement. The &lt;code&gt;with&lt;/code&gt; statement encircles a block of code.&lt;/p&gt;
&lt;p&gt;It is defined as:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;EXPRESSION&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;TARGET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;BLOCK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;where the &lt;em&gt;as TARGET&lt;/em&gt; part is optional.&lt;/p&gt;
&lt;p&gt;This is &lt;a href="https://snarky.ca/tag/syntactic-sugar/"&gt;Syntastic Sugar&lt;/a&gt; and
semantically equivalent to:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;manager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EXPRESSION&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;TARGET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__enter__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;BLOCK&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__exit__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exc_info&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__exit__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;TARGET will get the return value of the Context Manager’s &lt;code&gt;__enter__&lt;/code&gt; method.
The &lt;code&gt;__exit__&lt;/code&gt; method will be called either with the exception and traceback
information in case of an error, or when the code of BLOCK has finished. In case
of an error, the Context Manager can suppress the fall through of the error by
returning a truthy value from the &lt;code&gt;__exit__&lt;/code&gt; method. Otherwise the error will be
(re-)raised. Remember, not having a return statement in a method actually
returns &lt;code&gt;None&lt;/code&gt;, which evaluates to &lt;code&gt;False&lt;/code&gt;. Thus by default the error will be
(re-)raised.&lt;/p&gt;
&lt;p&gt;The with statement also allows to combine several context managers.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;With more than one item, the context managers are processed as if multiple
with statements were nested:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;a&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="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;BLOCK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;is semantically equivalent to:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;BLOCK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="https://docs.python.org/3/reference/compound_stmts.html#the-with-statement"&gt;Source&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In summary:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The Python with statement creates a runtime context that allows you to run
a group of statements under the control of a context manager. PEP 343 added
the with statement to make it possible to factor out standard use cases of
the try … finally statement.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Compared to traditional try … finally constructs, the with statement can
make your code clearer, safer, and reusable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://realpython.com/python-with-statement/#the-with-statement-approach"&gt;Source&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="implementing-a-context-manager-using-contextlib"&gt;Implementing a Context Manager using contextlib &lt;a class="header-anchor" href="#implementing-a-context-manager-using-contextlib"&gt;¶&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;When implementing a context manager as a class it may be difficult to understand
the actual call flow. Therefore Python provides tools in the standard library
for implementing a context manager using a function.&lt;/p&gt;
&lt;p&gt;Using &lt;a href="https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager"&gt;contextlib.contextmanager&lt;/a&gt;
decorator allows for implementing a &lt;code&gt;Context Manager&lt;/code&gt; easily by using a
&lt;a href="https://docs.python.org/3/reference/datamodel.html#generator-functions"&gt;generator function&lt;/a&gt;.
Take a look at the following code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;contextlib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;contextmanager&lt;/span&gt;

&lt;span class="nd"&gt;@contextmanager&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;managed_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Code to acquire resource, e.g.:&lt;/span&gt;
    &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;acquire_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;
    &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Code to release resource, e.g.:&lt;/span&gt;
        &lt;span class="n"&gt;release_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is equivalent to the following class based context manager:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;managed_resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__enter__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;acquire_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__exit__&lt;/span&gt;&lt;span class="p"&gt;(&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;exc_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exc_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exc_traceback&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;release_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The function based context manager is easier to read and to follow.&lt;/p&gt;
&lt;p&gt;To understand what &lt;code&gt;contextmanger&lt;/code&gt; decorator does actually internally, a
(simplified) version of the decorator itself could be implemented as:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;GeneratorContextManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&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;generator&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;generator&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__enter__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__exit__&lt;/span&gt;&lt;span class="p"&gt;(&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;exc_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exc_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exc_traceback&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;exc_type&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
               &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;StopIteration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
               &lt;span class="k"&gt;return&lt;/span&gt;
       &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
               &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;throw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exc_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exc_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exc_traceback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;StopIteration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
               &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
           &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;raise&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;contextmanager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generator_func&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&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;GeneratorContextManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generator_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&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;wrapper&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="https://peps.python.org/pep-0343/#generator-decorator"&gt;Source&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="capture-the-call-flow"&gt;Capture the Call Flow &lt;a class="header-anchor" href="#capture-the-call-flow"&gt;¶&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;To explain the code from the previous chapters and to understand its call flow
easily, two simple context managers can be implemented.&lt;/p&gt;
&lt;p&gt;A class based Context Manager:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;SimpleContextManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__enter__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;acquire&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;resource&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__exit__&lt;/span&gt;&lt;span class="p"&gt;(&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;exc_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exc_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exc_traceback&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;release&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;SimpleContextManager&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;SimpleContextManager&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;acquire&lt;/span&gt;
&lt;span class="n"&gt;resource&lt;/span&gt;
&lt;span class="n"&gt;release&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Via &lt;code&gt;contextlib.contextmanager&lt;/code&gt; decorator:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;contextlib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;contextmanager&lt;/span&gt;

&lt;span class="nd"&gt;@contextmanager&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;simple_context_manager&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;acquire&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;resource&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;release&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;simple_context_manager&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Output&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;simple_context_manager&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;acquire&lt;/span&gt;
&lt;span class="n"&gt;resource&lt;/span&gt;
&lt;span class="n"&gt;release&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id="example-context-managers"&gt;Example Context Managers &lt;a class="header-anchor" href="#example-context-managers"&gt;¶&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;To express the usefulness and flexibility of Context Managers, let me show you
some additional examples for using Context Manager even beyond strict resource
acquisition and release.&lt;/p&gt;
&lt;h2 id="example-1---redirect-stdout"&gt;Example 1 - Redirect Stdout &lt;a class="header-anchor" href="#example-1---redirect-stdout"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A Context Manager to redirect stdout to some other IO object.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;RedirectStdout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&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;new_target&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_new_stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_target&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_old_stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__enter__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_old_stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;
        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_new_stdout&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_new_stdout&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__exit__&lt;/span&gt;&lt;span class="p"&gt;(&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;exc_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exc_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exc_traceback&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;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_old_stdout&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Usage:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;help.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RedirectStdout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A similar Context Manager is available in the Python standard library as
&lt;a href="https://docs.python.org/3/library/contextlib.html#contextlib.redirect_stdout"&gt;&lt;code&gt;contextlib.redirect_stdout&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="example-2---suppress-exceptions"&gt;Example 2 - Suppress Exceptions &lt;a class="header-anchor" href="#example-2---suppress-exceptions"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A Context Manager to suppress all raised exceptions.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;contextlib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;contextmanager&lt;/span&gt;

&lt;span class="nd"&gt;@contextmanager&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;catch_all&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Usage:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;catch_all&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;RuntimeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A related Context Manager is available in the Python standard library as
&lt;a href="https://docs.python.org/3/library/contextlib.html#contextlib.suppress"&gt;&lt;code&gt;contextlib.suppress&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="example-3---add-a-directory-to-the-python-module-search-path-temporarily"&gt;Example 3 - Add a directory to the Python module search path temporarily &lt;a class="header-anchor" href="#example-3---add-a-directory-to-the-python-module-search-path-temporarily"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;

&lt;span class="nd"&gt;@contextmanager&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;add_module_path&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="nb"&gt;str&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;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&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;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt;
    &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;try&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;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&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="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# path is not in sys.path&lt;/span&gt;
            &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Usage:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;add_module_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;./packages/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rich&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="example-4---print-prefix"&gt;Example 4 - Print Prefix &lt;a class="header-anchor" href="#example-4---print-prefix"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;PrintPrefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&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;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__enter__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__exit__&lt;/span&gt;&lt;span class="p"&gt;(&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;exc_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exc_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exc_traceback&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Usage:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;PrintPrefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;😀&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;are we happy now?&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;yes we are!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; with PrintPrefix(&amp;quot;😀&amp;quot;) as out:
...     out.print(&amp;quot;are we happy now?&amp;quot;)
...     out.print(&amp;quot;yes we are!&amp;quot;)
...
😀 are we happy now?
😀 yes we are!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id="links"&gt;Links &lt;a class="header-anchor" href="#links"&gt;¶&lt;/a&gt;&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/reference/datamodel.html#with-statement-context-managers"&gt;With Statement Context Managers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/stdtypes.html#typecontextmanager"&gt;Context Manager Types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://peps.python.org/pep-0343/"&gt;PEP 343 – The “with” Statement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://realpython.com/python-with-statement/"&gt;Real Python – Context Managers and Python’s with Statement&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content><category term="python"/><category term="python"/><category term="context-manager"/><category term="with-statement"/></entry><entry><title>xml.etree.ElementTree vs. lxml.etree</title><link href="https://bjoernricks.github.io/posts/python/stdlib-etree-vs-lxml-etree/" rel="alternate"/><published>2024-02-08T10:00:00+00:00</published><updated>2024-02-08T10:00:00+00:00</updated><author><name>Björn Ricks</name></author><id>tag:bjoernricks.github.io,2024-02-08:/posts/python/stdlib-etree-vs-lxml-etree/</id><summary type="html">&lt;p&gt;When working with XML and Python I often start with just using &lt;a href="https://lxml.de/tutorial.html"&gt;xml.etree.ElementTree&lt;/a&gt;
from Python’s standard library. It comes with Python and is sufficient for most
projects. But with quite big XML documents (&amp;gt; 1 GiB) parsing becomes slow
and &lt;a href="https://lxml.de/api.html#lxml-etree"&gt;lxml.etree&lt;/a&gt; shines.&lt;/p&gt;
&lt;a class="button is-link" href="posts/python/stdlib-etree-vs-lxml-etree/"&gt;Read more &lt;span class="icon is-small"&gt;&lt;i class="fa fa-angle-double-right"&gt;&lt;/i&gt;&lt;/span&gt;&lt;/a&gt;</summary><content type="html">&lt;p&gt;When working with XML and Python I often start with just using &lt;a href="https://lxml.de/tutorial.html"&gt;xml.etree.ElementTree&lt;/a&gt;
from Python’s standard library. It comes with Python and is sufficient for most
projects. But with quite big XML documents (&amp;gt; 1 GiB) parsing becomes slow
and &lt;a href="https://lxml.de/api.html#lxml-etree"&gt;lxml.etree&lt;/a&gt; shines.&lt;/p&gt;
&lt;!-- TEASER_END --&gt;
&lt;p&gt;While exchanging some code using &lt;a href="https://lxml.de/tutorial.html"&gt;xml.etree.ElementTree&lt;/a&gt; to &lt;a href="https://lxml.de/api.html#lxml-etree"&gt;lxml&lt;/a&gt; I’ve
found some slightly differences in their implementation despite sharing the same
API.&lt;/p&gt;
&lt;h1 id="namespaces"&gt;Namespaces &lt;a class="header-anchor" href="#namespaces"&gt;¶&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;XML Namespaces can be used with a special syntax &lt;a href="https://docs.python.org/3/library/xml.etree.elementtree.html#parsing-xml-with-namespaces"&gt;&lt;code&gt;{namespace-uri}tag-name&lt;/code&gt;&lt;/a&gt; as tags.
To map a namespace to a specific prefix with &lt;a href="https://lxml.de/tutorial.html"&gt;stdlib etree&lt;/a&gt;, it requires
to &lt;a href="https://docs.python.org/3/library/xml.etree.elementtree.html#xml.etree.ElementTree.register_namespace"&gt;register the prefix/uri combination globally&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lxml.de/api.html#lxml-etree"&gt;lxml&lt;/a&gt; supports the same &lt;code&gt;{namespace-uri}tag-name&lt;/code&gt; syntax but allows to register
a namespace map (a dict of namespace prefix to uri mapping) on every &lt;a href="https://lxml.de/tutorial.html#namespaces"&gt;Element&lt;/a&gt;
during creation via a &lt;code&gt;nsmap&lt;/code&gt; keyword argument.&lt;/p&gt;
&lt;h1 id="default-namespace"&gt;Default Namespace &lt;a class="header-anchor" href="#default-namespace"&gt;¶&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://docs.python.org/3/library/xml.etree.elementtree.html#xml.etree.ElementTree.register_namespace"&gt;Registering&lt;/a&gt; the default namespace requires to pass an empty string &lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt; as
prefix with &lt;a href="https://lxml.de/tutorial.html"&gt;stdlib etree&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With &lt;a href="https://lxml.de/api.html#lxml-etree"&gt;lxml&lt;/a&gt; registering the default namespace requires to use &lt;code&gt;None&lt;/code&gt; as key for
the prefix in the namespace mapping dict. Using an empty string &lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt; instead
will raise an exception.&lt;/p&gt;
&lt;p&gt;With lxml it is not possible to &lt;a href="https://docs.python.org/3/library/xml.etree.elementtree.html#xml.etree.ElementTree.register_namespace"&gt;register a default namespace globally&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At the end the namespace handling of lxml is superior because namespaces are not
defined globally. For example this allow to test them independently without
interference.&lt;/p&gt;
&lt;h1 id="serialization"&gt;Serialization &lt;a class="header-anchor" href="#serialization"&gt;¶&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;When &lt;a href="https://docs.python.org/3/library/xml.etree.elementtree.html#xml.etree.ElementTree.ElementTree.write"&gt;writing a XML document&lt;/a&gt; with &lt;a href="https://lxml.de/tutorial.html"&gt;stdlib etree&lt;/a&gt;
only the used namespaces will be serialized. Unused but registered namespaces
will be skipped and not included in the output.&lt;/p&gt;
&lt;p&gt;With &lt;a href="https://lxml.de/api.html#lxml-etree"&gt;lxml&lt;/a&gt; all namespaces passed as a namespace map will be included in the
output wether they are used or not.&lt;/p&gt;
&lt;p&gt;Setting &lt;code&gt;xml_declaration&lt;/code&gt; to &lt;code&gt;True&lt;/code&gt; and using &lt;code&gt;utf-8&lt;/code&gt; as &lt;code&gt;encoding&lt;/code&gt; will write
the encoding in upper cases as &lt;code&gt;&amp;lt;?xml version='1.0' encoding='UTF-8'?&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lxml.de/tutorial.html"&gt;stdlib etree&lt;/a&gt; supports a &lt;code&gt;unicode&lt;/code&gt; “encoding”. When using this “encoding” it is
possible to pass a &lt;a href="https://docs.python.org/3/library/io.html#io.TextIOBase"&gt;TextIOBase&lt;/a&gt; stream to the &lt;a href="https://docs.python.org/3/library/xml.etree.elementtree.html#xml.etree.ElementTree.ElementTree.write"&gt;&lt;code&gt;write&lt;/code&gt;&lt;/a&gt; function and &lt;code&gt;utf-8&lt;/code&gt; is used as the real
encoding.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lxml.de/api.html#lxml-etree"&gt;lxml etree&lt;/a&gt; only supports binary &lt;a href="https://docs.python.org/3/library/io.html#io.RawIOBase"&gt;RawIOBase&lt;/a&gt;
streams for the &lt;a href="https://docs.python.org/3/library/xml.etree.elementtree.html#xml.etree.ElementTree.ElementTree.write"&gt;&lt;code&gt;write&lt;/code&gt;&lt;/a&gt; function.&lt;/p&gt;
</content><category term="python"/><category term="python"/><category term="xml"/><category term="lxml"/><category term="etree"/><category term="elementtree"/></entry><entry><title>What's new in Python 3</title><link href="https://bjoernricks.github.io/posts/python/what-s-new-in-python/" rel="alternate"/><published>2023-11-10T09:58:50+00:00</published><updated>2023-12-22T07:00:00+00:00</updated><author><name>Björn Ricks</name></author><id>tag:bjoernricks.github.io,2023-11-10:/posts/python/what-s-new-in-python/</id><summary type="html">&lt;p&gt;Quick overview about the most important additions in a Python release&lt;/p&gt;
&lt;nav&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#python-312"&gt;Python 3.12 &lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#typing"&gt;Typing &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#f-strings"&gt;f-strings &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#pathlib"&gt;Pathlib &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#itertools"&gt;Itertools &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#python-311"&gt;Python 3.11 &lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#features"&gt;Features &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#typing-1"&gt;Typing &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#enum"&gt;Enum &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#asyncio"&gt;AsyncIO &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#python-310"&gt;Python 3.10 &lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#features-1"&gt;Features &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#typing-2"&gt;Typing &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#dataclasses"&gt;Dataclasses &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#asyncio-1"&gt;AsyncIO &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#python-39"&gt;Python 3.9 &lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#features-2"&gt;Features &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#typing-3"&gt;Typing &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#asyncio-2"&gt;AsyncIO &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/nav&gt;
&lt;a class="button is-link" href="posts/python/what-s-new-in-python/"&gt;Read more &lt;span class="icon is-small"&gt;&lt;i class="fa fa-angle-double-right"&gt;&lt;/i&gt;&lt;/span&gt;&lt;/a&gt;</summary><content type="html">&lt;p&gt;Quick overview about the most important additions in a Python release&lt;/p&gt;
&lt;nav&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#python-312"&gt;Python 3.12 &lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#typing"&gt;Typing &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#f-strings"&gt;f-strings &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#pathlib"&gt;Pathlib &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#itertools"&gt;Itertools &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#python-311"&gt;Python 3.11 &lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#features"&gt;Features &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#typing-1"&gt;Typing &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#enum"&gt;Enum &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#asyncio"&gt;AsyncIO &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#python-310"&gt;Python 3.10 &lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#features-1"&gt;Features &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#typing-2"&gt;Typing &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#dataclasses"&gt;Dataclasses &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#asyncio-1"&gt;AsyncIO &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#python-39"&gt;Python 3.9 &lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#features-2"&gt;Features &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#typing-3"&gt;Typing &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#asyncio-2"&gt;AsyncIO &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/nav&gt;
&lt;!-- TEASER_END --&gt;
&lt;h1 id="python-312"&gt;Python 3.12 &lt;a class="header-anchor" href="#python-312"&gt;¶&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://docs.python.org/3/whatsnew/3.12.html"&gt;https://docs.python.org/3/whatsnew/3.12.html&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="typing"&gt;Typing &lt;a class="header-anchor" href="#typing"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Type Parameter Syntax &lt;a href="https://peps.python.org/pep-0695/"&gt;PEP 695&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;ClassA&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;method1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&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;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;instead of&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;typing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Generic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TypeVar&lt;/span&gt;

&lt;span class="n"&gt;_T_co&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TypeVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;_T_co&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;covariant&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bound&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;ClassA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Generic&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_T_co&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;method1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&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;_T_co&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/typing.html#typing.override"&gt;@override decorator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;log_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nd"&gt;@override&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;log_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# Okay: overrides Base.log_status&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;

    &lt;span class="nd"&gt;@override&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;done&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# Error reported by type checker&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="f-strings"&gt;f-strings &lt;a class="header-anchor" href="#f-strings"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;f-strings have been formalized. Before Python 3.12 there was an extra separated
parser just for evaluating the f-strings. With Python 3.12 parsing f-strings has
been integrated and the PEG parser (introduced with Python 3.9).&lt;/p&gt;
&lt;p&gt;This comes with great improvements like being able to use quotes within quotes
and f-strings within f-strings.&lt;/p&gt;
&lt;p&gt;Examples:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Python &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;major&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;minor&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Names: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; &amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;John&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Paul&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Marie&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="pathlib"&gt;Pathlib &lt;a class="header-anchor" href="#pathlib"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/pathlib.html#pathlib.Path.walk"&gt;Path.walk&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="itertools"&gt;Itertools &lt;a class="header-anchor" href="#itertools"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/itertools.html#itertools.batched"&gt;itertools.batched&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="python-311"&gt;Python 3.11 &lt;a class="header-anchor" href="#python-311"&gt;¶&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://docs.python.org/3/whatsnew/3.11.html"&gt;https://docs.python.org/3/whatsnew/3.11.html&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="features"&gt;Features &lt;a class="header-anchor" href="#features"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/whatsnew/3.11.html#faster-cpython"&gt;Faster CPython&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;tomllib — Support for parsing TOML in the Standard Library &lt;a href="https://peps.python.org/pep-0680/"&gt;PEP 680&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Exception Groups and except* &lt;a href="https://peps.python.org/pep-0654/"&gt;PEP 654&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/contextlib.html#contextlib.chdir"&gt;&lt;code&gt;with contextlib.chdir(directory):&lt;/code&gt; &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="typing-1"&gt;Typing &lt;a class="header-anchor" href="#typing-1"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Self Type &lt;a href="https://peps.python.org/pep-0673/"&gt;PEP 673&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/typing.html#typing.LiteralString"&gt;LiteralString&lt;/a&gt; &lt;a href="https://peps.python.org/pep-0675/"&gt;PEP 675&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/typing.html#typing.overload"&gt;@overload decorator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="enum"&gt;Enum &lt;a class="header-anchor" href="#enum"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/enum.html#enum.StrEnum"&gt;StrEnum&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="asyncio"&gt;AsyncIO &lt;a class="header-anchor" href="#asyncio"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/asyncio-task.html#asyncio.TaskGroup"&gt;TaskGroup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Implementation of trio’s cancel scope feature with &lt;a href="https://docs.python.org/3.11/library/asyncio-task.html#asyncio.timeout"&gt;timeout&lt;/a&gt; and &lt;a href="https://docs.python.org/3.11/library/asyncio-task.html#asyncio.timeout_at"&gt;timeout_at&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="python-310"&gt;Python 3.10 &lt;a class="header-anchor" href="#python-310"&gt;¶&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://docs.python.org/3/whatsnew/3.10.html"&gt;https://docs.python.org/3/whatsnew/3.10.html&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="features-1"&gt;Features &lt;a class="header-anchor" href="#features-1"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Structural Pattern Matching &lt;a href="https://peps.python.org/pep-0634/"&gt;PEP 634&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="typing-2"&gt;Typing &lt;a class="header-anchor" href="#typing-2"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Allow writing union types as &lt;code&gt;X | Y&lt;/code&gt; &lt;a href="https://peps.python.org/pep-0604/"&gt;PEP 604&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="dataclasses"&gt;Dataclasses &lt;a class="header-anchor" href="#dataclasses"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Added slots parameter&lt;/li&gt;
&lt;li&gt;Keyword-only fields&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="asyncio-1"&gt;AsyncIO &lt;a class="header-anchor" href="#asyncio-1"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;async versions of iter and next called &lt;a href="https://github.com/python/cpython/issues/76042"&gt;aiter and anext&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="python-39"&gt;Python 3.9 &lt;a class="header-anchor" href="#python-39"&gt;¶&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://docs.python.org/3/whatsnew/3.9.html"&gt;https://docs.python.org/3/whatsnew/3.9.html&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="features-2"&gt;Features &lt;a class="header-anchor" href="#features-2"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;PEG language parser &lt;a href="https://peps.python.org/pep-0617/"&gt;PEP 617&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Zoneinfo module &lt;a href="https://peps.python.org/pep-0615/"&gt;PEP 615&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="typing-3"&gt;Typing &lt;a class="header-anchor" href="#typing-3"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Type Hinting Generics In Standard Collections &lt;a href="https://peps.python.org/pep-0585/"&gt;PEP 585&lt;/a&gt;
Examples: &lt;code&gt;list[str]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Flexible function and variable annotations - &lt;code&gt;Annotated&lt;/code&gt; &lt;a href="https://peps.python.org/pep-0593/"&gt;PEP 593&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="asyncio-2"&gt;AsyncIO &lt;a class="header-anchor" href="#asyncio-2"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/asyncio-task.html#asyncio.to_thread"&gt;asyncio.to_thread&lt;/a&gt; -&amp;gt; for running IO-bound functions in a separate thread to avoid blocking the event loop&lt;/li&gt;
&lt;/ul&gt;
</content><category term="python"/><category term="python"/><category term="news"/><category term="features"/></entry></feed>