{"id":626,"date":"2022-04-13T07:18:00","date_gmt":"2022-04-13T07:18:00","guid":{"rendered":"https:\/\/tbekk.com\/devstream\/?p=626"},"modified":"2022-04-21T08:28:19","modified_gmt":"2022-04-21T08:28:19","slug":"python-3-11-is-coming-heres-how-it-fares-against-python-3-10","status":"publish","type":"post","link":"https:\/\/tbekk.com\/devstream\/2022\/04\/13\/python-3-11-is-coming-heres-how-it-fares-against-python-3-10\/","title":{"rendered":"Python 3.11 is Coming! Here\u2019s How It Fares Against Python 3.10"},"content":{"rendered":"\n<p>A look at the new Python 3.11 features<\/p>\n\n\n\n<hr class=\"wp-block-separator is-style-wide\"\/>\n\n\n\n<ul class=\"wp-block-list\"><li><em><strong>Link: <\/strong><a href=\"https:\/\/betterprogramming.pub\/python-3-11-is-coming-heres-how-it-fares-against-python-3-10-675c00a28d4b\">https:\/\/betterprogramming.pub\/python-3-11-is-coming-heres-how-it-fares-against-python-3-10-675c00a28d4b<\/a><\/em><\/li><li><em><strong>Author: <\/strong>Eldad Uzman<\/em><\/li><li><em><strong>Publication date: <\/strong>April 10, 2022<\/em><\/li><\/ul>\n\n\n\n<hr class=\"wp-block-separator is-style-wide\"\/>\n\n\n\n<p id=\"5c9d\">According to the Python Software Foundation (PSF), Python 3.11 is in it\u2019s 7th alpha revision and is planned to be released in&nbsp;<a href=\"https:\/\/peps.python.org\/pep-0664\/#schedule\" rel=\"noreferrer noopener\" target=\"_blank\">October 2022<\/a>.<\/p>\n\n\n\n<p id=\"013e\">What changes are included for the upcoming version?<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"0072\">Prolog<\/h1>\n\n\n\n<p id=\"93c9\">To evaluate the differences between version 3.10 and 3.11, I\u2019ve set up 2 docker containers.<\/p>\n\n\n\n<p id=\"0823\">First container for version 3.10:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">docker run -t -d python:3.10.4-bullseye<\/pre>\n\n\n\n<p id=\"1b6e\">Second container for version 3.11:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">docker run -t -d python:3.11-rc-bullseye<\/pre>\n\n\n\n<p id=\"557e\">Having the two containers running I can use&nbsp;<a href=\"https:\/\/code.visualstudio.com\/docs\/remote\/containers\" rel=\"noreferrer noopener\" target=\"_blank\">vs code remote container<\/a>&nbsp;to attach to the running containers.<\/p>\n\n\n\n<p id=\"8c18\">Then I can execute my Python code in the two environments and see the difference.<\/p>\n\n\n\n<p id=\"9ab2\">In the following sections, I\u2019ll first show a code example, and then I\u2019ll show the difference between the two versions.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"51e7\">1: Error Location<\/h1>\n\n\n\n<p><a href=\"https:\/\/betterprogramming.pub\/media\/4443487366d6fb372ef20c5814361436\">https:\/\/betterprogramming.pub\/media\/4443487366d6fb372ef20c5814361436<\/a><\/p>\n\n\n\n<p id=\"34e7\">Output in version 3.10:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">1<br>100<br>Traceback (most recent call last):<br>  File \"\/usr\/local\/lib\/python3.10\/runpy.py\", line 196, in _run_module_as_main<br>    return _run_code(code, main_globals, None,<br>  File \"\/usr\/local\/lib\/python3.10\/runpy.py\", line 86, in _run_code<br>    exec(code, run_globals)<br>  File \"\/root\/py310\/myapp\/__main__.py\", line 4, in &lt;module&gt;<br>    print(d[\"key_11\"])<br>KeyError: 'key_11'<\/pre>\n\n\n\n<p id=\"84da\">Output in version 3.11<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">1<br>100<br>Traceback (most recent call last):<br>  File \"&lt;frozen runpy&gt;\", line 198, in _run_module_as_main<br>  File \"&lt;frozen runpy&gt;\", line 88, in _run_code<br>  File \"\/root\/py311\/myapp\/__main__.py\", line 4, in &lt;module&gt;<br>    print(d[\"key_11\"])<br>          ~^^^^^^^^^^<br>KeyError: 'key_11'<\/pre>\n\n\n\n<p id=\"906b\">Python 3.11 discloses a better error location to the developer making an awesome developer experience.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"d8a8\">2: The \u2018<code>self\u2019&nbsp;<\/code>type<\/h1>\n\n\n\n<p id=\"7a59\">The&nbsp;<code>self<\/code>&nbsp;type has already been introduced in the&nbsp;<code>typing extensions<\/code>&nbsp;<a href=\"https:\/\/pypi.org\/project\/typing-extensions\/\" rel=\"noreferrer noopener\" target=\"_blank\">module<\/a>&nbsp;and now it\u2019s promoted to the standard typing library.https:\/\/betterprogramming.pub\/media\/2af9a76f625df0b92bd8bbe785fd6232<\/p>\n\n\n\n<p id=\"ca11\">The code above represents the structure of a directory. Directories have subdirectories so the definition is recursive.<\/p>\n\n\n\n<p id=\"2340\">Output in Python 3.10:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Traceback (most recent call last):<br>  File \"\/usr\/local\/lib\/python3.10\/runpy.py\", line 196, in _run_module_as_main<br>    return _run_code(code, main_globals, None,<br>  File \"\/usr\/local\/lib\/python3.10\/runpy.py\", line 86, in _run_code<br>    exec(code, run_globals)<br>  File \"\/root\/py310\/myapp\/__main__.py\", line 2, in &lt;module&gt;<br>    from typing import List, Tuple, Self<\/pre>\n\n\n\n<p id=\"32c5\">Output in Python 3.11:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">{'content': (['a.txt', 'b.txt'],<br>             [{'content': (['file1', 'file2'], None), 'name': 'dir1'}]),<br> 'name': 'dir2'}<\/pre>\n\n\n\n<p id=\"96ff\">Note: You can annotate the type of the&nbsp;<code>subdir<\/code>&nbsp;by the name of the class itself. But if the parent class name changes you\u2019d have to change all the annotation references accordingly.<\/p>\n\n\n\n<p id=\"a9ab\">In order for this code to work in 3.11 and 3.10 you can perform importing as follow:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">try:<br>    from typing import Self<br>except ImportError:<br>    from typing_extensions import Self<\/pre>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"a0c5\">3: Exception note<\/h1>\n\n\n\n<p id=\"eac1\">The&nbsp;<code>BaseException<\/code>&nbsp;class now has a&nbsp;<code>__note__<\/code>&nbsp;class attribute defaults to&nbsp;<code>None<\/code>.<br>You can override it with any string of your choice and provide further information.https:\/\/betterprogramming.pub\/media\/021b0ccfc98187a751da8f310dbea4c3<\/p>\n\n\n\n<p id=\"7004\">Output in Python 3.10:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Traceback (most recent call last):<br>  File \"\/usr\/local\/lib\/python3.10\/runpy.py\", line 196, in _run_module_as_main<br>    return _run_code(code, main_globals, None,<br>  File \"\/usr\/local\/lib\/python3.10\/runpy.py\", line 86, in _run_code<br>    exec(code, run_globals)<br>  File \"\/root\/py310\/myapp\/__main__.py\", line 6, in &lt;module&gt;<br>    raise MyException(\"some exception\")<br>__main__.MyException: some exception<\/pre>\n\n\n\n<p id=\"5ea2\">Output in Python 3.11:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Traceback (most recent call last):<br>  File \"&lt;frozen runpy&gt;\", line 198, in _run_module_as_main<br>  File \"&lt;frozen runpy&gt;\", line 88, in _run_code<br>  File \"\/root\/py311\/myapp\/__main__.py\", line 6, in &lt;module&gt;<br>    raise MyException(\"some exception\")<br>    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br>MyException: some exception<br>this is my note :)<\/pre>\n\n\n\n<p id=\"6534\">We see that the note has been added to the output and it allows developers to be more communicative in their exceptions.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"4847\">4: Exception groups<\/h1>\n\n\n\n<p id=\"c927\">Version 3.11 introduces a new exception type name&nbsp;<code>ExceptionGroup<\/code>&nbsp;to throw a bundle of exceptions and handle them in an&nbsp;<code>except<\/code>&nbsp;clause.<\/p>\n\n\n\n<p id=\"605a\">In addition to that a new&nbsp;<code>except*<\/code>&nbsp;syntax is introduced.https:\/\/betterprogramming.pub\/media\/3dd7c186e9002701cb58e5061eb1c528<\/p>\n\n\n\n<p id=\"cb0c\">Output in Python 3.10:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">File \"\/usr\/local\/lib\/python3.10\/runpy.py\", line 189, in _run_module_as_main<br>    mod_name, mod_spec, code = _get_main_module_details(_Error)<br>  File \"\/usr\/local\/lib\/python3.10\/runpy.py\", line 223, in _get_main_module_details<br>    return _get_module_details(main_name)<br>  File \"\/usr\/local\/lib\/python3.10\/runpy.py\", line 157, in _get_module_details<br>    code = loader.get_code(mod_name)<br>  File \"&lt;frozen importlib._bootstrap_external&gt;\", line 1017, in get_code<br>  File \"&lt;frozen importlib._bootstrap_external&gt;\", line 947, in source_to_code<br>  File \"&lt;frozen importlib._bootstrap&gt;\", line 241, in _call_with_frames_removed<br>  File \"\/root\/py310\/myapp\/__main__.py\", line 18<br>    except * (ToYoungException, EmailIsInvalidException) as exception_group_1:<\/pre>\n\n\n\n<p id=\"06ef\">Output in Python 3.11:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">validations failed<br>  + Exception Group Traceback (most recent call last):<br>  |   File \"&lt;frozen runpy&gt;\", line 198, in _run_module_as_main<br>  |   File \"&lt;frozen runpy&gt;\", line 88, in _run_code<br>  | ExceptionGroup:  (1 sub-exception)<br>  +-+---------------- 1 ----------------<br>    | Exception Group Traceback (most recent call last):<br>    |   File \"\/root\/py311\/myapp\/__main__.py\", line 14, in &lt;module&gt;<br>    |     raise ExceptionGroup(<br>    |     ^^^^^^^^^^^^^^^^^^^^^<br>    | ExceptionGroup: Data validations (2 sub-exceptions)<br>    +-+---------------- 1 ----------------<br>      | ToYoungException: Age must be over 18 - age is 11<br>      +---------------- 2 ----------------<br>      | EmailIsInvalidException: Email must be valid some_wannabe_email<br>      +------------------------------------<br>    | <br>    | The above exception was the direct cause of the following exception:<br>    | <br>    | Traceback (most recent call last):<br>    |   File \"\/root\/py311\/myapp\/__main__.py\", line 20, in &lt;module&gt;<br>    |     raise ValueError from exception_group_1<br>    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br>    | ValueError<br>    +------------------------------------<\/pre>\n\n\n\n<p id=\"98f2\">As we can see, it is highly valuable when we have multiple failure reasons which we want to disclose in one go.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"1a1d\">5. Nested Async Comprehensions<\/h1>\n\n\n\n<p><a href=\"https:\/\/betterprogramming.pub\/media\/1d94827ee982a2e1415a229294f2242f\">https:\/\/betterprogramming.pub\/media\/1d94827ee982a2e1415a229294f2242f<\/a><\/p>\n\n\n\n<p id=\"afe8\">Output in Python 3.10:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Traceback (most recent call last):<br>  File \"\/usr\/local\/lib\/python3.10\/runpy.py\", line 189, in _run_module_as_main<br>    mod_name, mod_spec, code = _get_main_module_details(_Error)<br>  File \"\/usr\/local\/lib\/python3.10\/runpy.py\", line 223, in _get_main_module_details<br>    return _get_module_details(main_name)<br>  File \"\/usr\/local\/lib\/python3.10\/runpy.py\", line 157, in _get_module_details<br>    code = loader.get_code(mod_name)<br>  File \"&lt;frozen importlib._bootstrap_external&gt;\", line 1017, in get_code<br>  File \"&lt;frozen importlib._bootstrap_external&gt;\", line 947, in source_to_code<br>  File \"&lt;frozen importlib._bootstrap&gt;\", line 241, in _call_with_frames_removed<br>  File \"\/root\/py310\/myapp\/__main__.py\", line 11<br>    return { n: [x async for x in elements(n)] for n in range(3)}<br>                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br>SyntaxError: asynchronous comprehension outside of an asynchronous function<\/pre>\n\n\n\n<p id=\"3db5\">Output in Python 3.11:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">{0: [1], 1: [1, 1], 2: [1, 2, 4], 3: [1, 3, 9, 27], 4: [1, 4, 16, 64, 256]}<\/pre>\n\n\n\n<p id=\"afdf\">The moment the code enters a comprehension block it&#8217;s now aware of the comprehension as to its current \u201cfunction context\u201d.<br>If the comprehension is not asynchronous then the inner code block can not have asynchronous statements.<\/p>\n\n\n\n<p id=\"5cd2\">In Python 3.11 though, comprehensions become implicitly asynchronous if they contain inner&nbsp;<code>async&nbsp;<\/code>statements that allows for inner&nbsp;<code>async<\/code>&nbsp;comprehensions.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"1887\">6: TOML parser<\/h1>\n\n\n\n<p id=\"278a\"><a href=\"https:\/\/en.wikipedia.org\/wiki\/TOML\" rel=\"noreferrer noopener\" target=\"_blank\">TOML&nbsp;<\/a>parsing is now part of the standard library just like JSON and CSV.https:\/\/betterprogramming.pub\/media\/6f2cef1c457ef9538367ec0e0d5994aa<\/p>\n\n\n\n<p id=\"590f\">Output in Python 3.10:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Traceback (most recent call last):<br>  File \"\/usr\/local\/lib\/python3.10\/runpy.py\", line 196, in _run_module_as_main<br>    return _run_code(code, main_globals, None,<br>  File \"\/usr\/local\/lib\/python3.10\/runpy.py\", line 86, in _run_code<br>    exec(code, run_globals)<br>  File \"\/root\/py310\/myapp\/__main__.py\", line 2, in &lt;module&gt;<br>    import tomllib<br>ModuleNotFoundError: No module named 'tomllib'<\/pre>\n\n\n\n<p id=\"821f\">Output in Python 3.11:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">{'clients': {'data': [['gamma', 'delta'], [1, 2]], 'hosts': ['alpha', 'omega']},<br> 'database': {'connection_max': 5000,<br>              'enabled': True,<br>              'ports': [8000, 8001, 8002],<br>              'server': '192.168.1.1'},<br> 'owner': {'dob': datetime.datetime(1979, 5, 27, 7, 32, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=57600))),<br>           'name': 'Tom Preston-Werner'},<br> 'servers': {'alpha': {'dc': 'eqdc10', 'ip': '10.0.0.1'},<br>             'beta': {'dc': 'eqdc10', 'ip': '10.0.0.2'}},<br> 'title': 'TOML Example'}<\/pre>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"b929\">7. Performance Optimization<\/h1>\n\n\n\n<p id=\"81ba\">It\u2019s argued that Python 3.11 is 10\u201360% faster in run time compared to python 3.10. You can read more about it in the benchmarking section&nbsp;<a href=\"https:\/\/github.com\/faster-cpython\/ideas\/blob\/main\/main-vs-310.rst\" rel=\"noreferrer noopener\" target=\"_blank\">here<\/a>.<\/p>\n\n\n\n<p id=\"132a\">Python 3.11 is coming with a suite of improvements, both in performance and developer experience.<\/p>\n\n\n\n<p id=\"9927\">Learn these updates and up your programming game!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A look at the new Python 3.11 features Link: https:\/\/betterprogramming.pub\/python-3-11-is-coming-heres-how-it-fares-against-python-3-10-675c00a28d4b Author: Eldad Uzman Publication date: April 10, 2022 According to the Python Software Foundation (PSF), Python 3.11 is in it\u2019s&#8230; <a class=\"read-more-link\" href=\"https:\/\/tbekk.com\/devstream\/2022\/04\/13\/python-3-11-is-coming-heres-how-it-fares-against-python-3-10\/\">Read more &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[51,10,65],"tags":[143],"class_list":["post-626","post","type-post","status-publish","format-standard","hentry","category-article","category-development","category-lang","tag-python-3-11"],"_links":{"self":[{"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/posts\/626","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/comments?post=626"}],"version-history":[{"count":5,"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/posts\/626\/revisions"}],"predecessor-version":[{"id":631,"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/posts\/626\/revisions\/631"}],"wp:attachment":[{"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/media?parent=626"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/categories?post=626"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/tags?post=626"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}