This repository holds example code that demos some of the new features in Python 3.11.
You need Python 3.11 installed to run these examples. See the following tutorial instructions:
You can learn more about Python 3.11's new features in the following Real Python tutorials:
- Python 3.11 Preview: Even Better Error Messages
- Python 3.11 Preview: Task and Exception Groups
- Python 3.11 Preview: TOML and
tomllib
You'll find examples from all these tutorials in this repository.
Create and activate a virtual environment:
$ python -m venv venv
$ source venv/bin/activate
Install necessary dependencies for the examples (see requirements.in
):
(venv) $ python -m pip install colorama parse
Alternatively, you can install dependencies from requirements.txt
if you want to ensure that you're using the same versions of the third-party packages:
(venv) $ python -m pip install -r requirements.txt
These examples have been run with Python 3.11.0rc1, the first release candidate of Python 3.11.
This section only contains brief instructions on how you can run the examples. See the tutorials for technical details.
Load scientists.py
into your interactive REPL:
(venv) $ python -i scientists.py
You can then experiment with dict_to_person()
and convert_pair()
:
>>> dict_to_person(scientists[1])
Traceback (most recent call last):
...
File "/home/realpython/scientists.py", line 37, in dict_to_person
name=f"{info['name']['first']} {info['name']['last']}",
~~~~~~~~~~~~^^^^^^^^
KeyError: 'last'
>>> convert_pair(scientists[0], scientists[2])
Traceback (most recent call last):
...
File "/home/realpython/scientists.py", line 44, in convert_pair
return dict_to_person(first), dict_to_person(second)
^^^^^^^^^^^^^^^^^^^^^^
File "/home/realpython/scientists.py", line 38, in dict_to_person
life_span=(info["birth"]["year"], info["death"]["year"]),
~~~~~~~~~~~~~^^^^^^^^
TypeError: 'NoneType' object is not subscriptable
See Even Better Error Messages in Python 3.11 and PEP 657.
Use ExceptionGroup
and except*
to handle several errors at once:
(venv) $ python exception_group.py
Handling ValueErrors: (ValueError(654),)
+ Exception Group Traceback (most recent call last):
| File "/home/realpython/exception_group.py", line 2, in <module>
| raise ExceptionGroup(
| ExceptionGroup: group (2 sub-exceptions)
+-+---------------- 1 ----------------
| TypeError: str
+---------------- 2 ----------------
| TypeError: int
+------------------------------------
See Exception Groups and except*
in Python 3.11 and PEP 654.
Run count.py
, count_gather.py
, and count_taskgroup.py
and compare their behaviors. For example:
(venv) $ python count_taskgroup.py scientists.py rot13.txt count.py
scientists.py □□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□ (44)
Files with thirteen lines are too scary!
count.py □□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□ (32)
See Asynchronous Task Groups in Python 3.11 and BPO 46752.
python_info.toml
and tomli_pyproject.toml
show two examples of TOML files.
Use read_toml.py
to read them:
(venv) $ python read_toml.py python_info.toml tomli_pyproject.toml
======================python_info.toml======================
{'python': {'version': 3.11,
'release_manager': 'Pablo Galindo Salgado',
'is_beta': True,
'beta_release': 3,
'release_date': datetime.date(2022, 6, 16),
'peps': [657, 654, 678, 680, 673, 675, 646, 659]}}
====================tomli_pyproject.toml====================
{'build-system': {'requires': ['flit_core>=3.2.0,<4'],
'build-backend': 'flit_core.buildapi'},
'project': {'name': 'tomli',
'version': '2.0.1',
'description': "A lil' TOML parser",
'requires-python': '>=3.7',
'readme': 'README.md',
'keywords': ['toml'],
'urls': {'Homepage': 'https://github.com/hukkin/tomli',
'PyPI': 'https://pypi.org/project/tomli'}}}
You can use tomllib_w.py
to write simplified TOML files. write_toml.py
demonstrates how you can use it:
(venv) $ python write_toml.py
url = "https://realpython.com/python311-tomllib/"
[author]
name = "Geir Arne Hjelle"
email = "geirarne@realpython.com"
See tomllib
TOML Parser in Python 3.11 and PEP 680.
polar_point.py
uses Self
for annotation:
(venv) $ python polar_point.py
PolarPoint(r=5.0, φ=0.9272952180016122)
execute_sql.py
shows an example of LiteralString
:
(venv) $ python execute_sql.py
Pretending to execute: SELECT * FROM users
Pretending to execute: SELECT * FROM users
Enter table name: users; DROP TABLE users; --
Pretending to execute: SELECT * FROM users; DROP TABLE users; --
See Arbitrary Literal String Type and PEP 675.
ndarray.py
shows an example of using TypeVarTuple
.
See Variadic Generic Types and PEP 646.
Use .add_notes()
to annotate exceptions with custom notes:
(venv) $ python exception_notes.py
err.__notes__ = ['Enriching Exceptions with Notes', 'Python 3.11']
--------------------- Loop over notes ----------------------
Enriching Exceptions with Notes
Python 3.11
--------------- Notes are added to traceback ---------------
Traceback (most recent call last):
File "/home/realpython/exception_notes.py", line 12, in <module>
raise err
ValueError: 678
Enriching Exceptions with Notes
Python 3.11
See Annotate Exceptions With Custom Notes and PEP 678.
You can use sys.exception()
to access the active exception:
(venv) $ python active_exception.py
Handling bpo-46328
Handling bpo-46328
Note that this is typically not necessary in regular code. You can use the except ValueError as err
syntax instead.
See Reference the Active Exception With sys.exception()
and BPO 46328.
traceback_demo.py
shows that tracebacks can be consistently accessed through the exception object:
(venv) $ python traceback_demo.py
tb_last(exc_value.__traceback__) = 'bad_calculation:13'
tb_last(exc_tb) = 'bad_calculation:13'
See Reference the Active Traceback Consistently and BPO 45711.
You can use math.cbrt()
to calculate cube roots:
(venv) $ python cube_root.py
math.cbrt(729) = 9.000000000000002
729 ** (1 / 3) = 8.999999999999998
math.pow(729, 1 / 3) = 8.999999999999998
You can use math.exp2()
to calculate powers of two:
(venv) $ python power_of_two.py
math.exp2(16) = 65536.0
2**16 = 65536
math.pow(2, 16) = 65536.0
See Cube Roots and Powers of Two, BPO 44357 and BPO 45917.
You can use underscores when defining fractions from strings:
(venv) $ python underscore.py
Fraction('6_024/1_729') = 6024/1729
See Underscores in Fractions and BPO 44258.
The Norwegian calculator implemented in kalkulator.py
uses operator.call()
:
(venv) $ python kalkulator.py
20 pluss 22 = 42.0
2022 minus 1991 = 31.0
45 ganger 45 = 2025.0
11 delt på 3 = 3.6666666666666665
See Flexible Calling of Objects and BPO 44019.
- Geir Arne Hjelle, E-mail: geirarne@realpython.com
Distributed under the MIT license. See LICENSE
for more information.