Les nouveautés de Python 3.10

Rédacteur:

Pablo Galindo Salgado

This article explains the new features in Python 3.10, compared to 3.9. Python 3.10 was released on October 4, 2021. For full details, see the changelog.

Résumé – Points forts de la publication

Nouvelles fonctionnalités de syntaxe :

  • PEP 634, Filtrage par motifs structurels : spécification ;

  • PEP 635, Filtrage par motifs structurels : motivation et justification ;

  • PEP 636, Filtrage par motifs structurels : tutoriel ;

  • bpo-12782, Les gestionnaires de contextes entre parenthèses sont maintenant autorisés.

Nouvelles fonctionnalités dans la bibliothèque standard :

  • PEP 618, ajout de la vérification optionnelle de taille dans zip.

Améliorations de l'interpréteur :

  • PEP 626, numéros de lignes précis pour le débogage et les autres outils.

Nouvelles fonctionnalités de typage :

  • PEP 604, autorise l'écriture d'union de types sous la forme X | Y ;

  • PEP 612, variables de spécification de paramètres.

  • PEP 613, alias de types explicites ;

  • PEP 647, User-Defined Type Guards

Obsolescences, retraits ou restrictions :

  • PEP 644, mise à jour de la version minimale d'OpenSSL à 1.1.1 ;

  • PEP 632, obsolescence du module distutils ;

  • PEP 623, obsolescence et préparation du retrait du membre wstr de PyUnicodeObject ;

  • PEP 624, retrait des API d'encodage Py_UNICODE ;

  • PEP 597, ajout de l'EncodingWarning optionnel

Nouvelles fonctionnalités

Gestionnaires de contextes entre parenthèses

Il est maintenant possible de mettre les gestionnaires de contexte entre parenthèses pour les répartir sur plusieurs lignes. Ceci permet le formatage d'une longue série de gestionnaires de contexte sur plusieurs lignes comme ce qui était préalablement possible avec les instructions d'importation. Par exemple, tous ces blocs sont maintenant valides :

with (CtxManager() as example):
    ...

with (
    CtxManager1(),
    CtxManager2()
):
    ...

with (CtxManager1() as example,
      CtxManager2()):
    ...

with (CtxManager1(),
      CtxManager2() as example):
    ...

with (
    CtxManager1() as example1,
    CtxManager2() as example2
):
    ...

il est aussi possible d'utiliser une virgule en fin de ligne à la fin du groupe entre parenthèses :

with (
    CtxManager1() as example1,
    CtxManager2() as example2,
    CtxManager3() as example3,
):
    ...

Cette nouvelle syntaxe utilise la capacité non-LL(1) du nouvel analyseur syntaxique. Voir PEP 617 pour plus de détails.

(contribution de Guido van Rossum, Pablo Galindo et Lysandros Nikolaou dans bpo-12782 et bpo-40334).

Meilleurs messages d'erreurs

SyntaxError

Pendant l'analyse syntaxique de code qui contient des parenthèses ou autres balises ouvrantes et fermantes, l'interpréteur inclut maintenant l'emplacement de la balise ou parenthèse non fermée plutôt que d'afficher SyntaxError: unexpected EOF while parsing ou d'indiquer un emplacement incorrect. Par exemple, considérez le code suivant (remarquez l'accolade '{' non-fermée) :

expected = {9: 1, 18: 2, 19: 2, 27: 3, 28: 3, 29: 3, 36: 4, 37: 4,
            38: 4, 39: 4, 45: 5, 46: 5, 47: 5, 48: 5, 49: 5, 54: 6,
some_other_code = foo()

Les versions précédentes de l’interpréteur indiquaient des emplacements qui portaient à confusion pour l'erreur de syntaxe :

File "example.py", line 3
    some_other_code = foo()
                    ^
SyntaxError: invalid syntax

mais dans Python 3.10, une erreur plus informative est levée :

File "example.py", line 1
    expected = {9: 1, 18: 2, 19: 2, 27: 3, 28: 3, 29: 3, 36: 4, 37: 4,
               ^
SyntaxError: '{' was never closed

De façon similaire, les erreurs impliquant des chaînes littérales non-fermées (avec simples ou triples apostrophes) pointent maintenant vers le début de la chaîne plutôt de mentionner la fin de ligne ou la fin du fichier.

Ces améliorations sont inspirées par un travail préalable sur l'interpréteur PyPy

(contribution de Pablo Galindo dans bpo-42864 et Batuhan Taskaya dans bpo-40176).

Les exceptions SyntaxError levées par l'interpréteur soulignent maintenant toute la portée de l'expression qui constitue l'erreur de syntaxe plutôt que seulement la position où le problème a été détecté. De cette façon, plutôt que d'afficher (avant Python 3.10) :

>>> foo(x, z for z in range(10), t, w)
  File "<stdin>", line 1
    foo(x, z for z in range(10), t, w)
           ^
SyntaxError: Generator expression must be parenthesized

Python 3.10 affiche maintenant l'exception comme ceci :

>>> foo(x, z for z in range(10), t, w)
  File "<stdin>", line 1
    foo(x, z for z in range(10), t, w)
           ^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized

Cette amélioration est une contribution de Pablo Galindo dans bpo-43914.

Un nombre considérable de nouveaux messages spécialisés pour les exceptions SyntaxError a été incorporé. Certains des plus notables sont :

  • : manquant avant les blocs :

    >>> if rocket.position > event_horizon
      File "<stdin>", line 1
        if rocket.position > event_horizon
                                          ^
    SyntaxError: expected ':'
    

    (Contributed by Pablo Galindo in bpo-42997.)

  • Les n-uplets sans parenthèses dans les cibles de compréhensions :

    >>> {x,y for x,y in zip('abcd', '1234')}
      File "<stdin>", line 1
        {x,y for x,y in zip('abcd', '1234')}
         ^
    SyntaxError: did you forget parentheses around the comprehension target?
    

    (Contributed by Pablo Galindo in bpo-43017.)

  • virgules manquantes dans les littéraux de collections et entre les expressions ; :

    >>> items = {
    ... x: 1,
    ... y: 2
    ... z: 3,
      File "<stdin>", line 3
        y: 2
           ^
    SyntaxError: invalid syntax. Perhaps you forgot a comma?
    

    (Contributed by Pablo Galindo in bpo-43822.)

  • types multiples d'Exception sans parenthèses :

    >>> try:
    ...     build_dyson_sphere()
    ... except NotEnoughScienceError, NotEnoughResourcesError:
      File "<stdin>", line 3
        except NotEnoughScienceError, NotEnoughResourcesError:
               ^
    SyntaxError: multiple exception types must be parenthesized
    

    (Contributed by Pablo Galindo in bpo-43149.)

  • : et valeurs manquantes dans les littéraux de dictionnaires :

    >>> values = {
    ... x: 1,
    ... y: 2,
    ... z:
    ... }
      File "<stdin>", line 4
        z:
         ^
    SyntaxError: expression expected after dictionary key and ':'
    
    >>> values = {x:1, y:2, z w:3}
      File "<stdin>", line 1
        values = {x:1, y:2, z w:3}
                            ^
    SyntaxError: ':' expected after dictionary key
    

    (Contributed by Pablo Galindo in bpo-43823.)

  • blocs try sans blocs except ou finally :

    >>> try:
    ...     x = 2
    ... something = 3
      File "<stdin>", line 3
        something  = 3
        ^^^^^^^^^
    SyntaxError: expected 'except' or 'finally' block
    

    (Contributed by Pablo Galindo in bpo-44305.)

  • utilisation de = au lieu de == dans les comparaisons :

    >>> if rocket.position = event_horizon:
      File "<stdin>", line 1
        if rocket.position = event_horizon:
                           ^
    SyntaxError: cannot assign to attribute here. Maybe you meant '==' instead of '='?
    

    (Contributed by Pablo Galindo in bpo-43797.)

  • utilisation de * dans les chaînes formatées (f-strings) :

    >>> f"Black holes {*all_black_holes} and revelations"
      File "<stdin>", line 1
        (*all_black_holes)
         ^
    SyntaxError: f-string: cannot use starred expression here
    

    (Contributed by Pablo Galindo in bpo-41064.)

IndentationError

Plusieurs exceptions IndentationError ont maintenant plus de contexte concernant le genre de bloc qui attendait une indentation. Ceci inclut l'emplacement de l'instruction :

>>> def foo():
...    if lel:
...    x = 2
  File "<stdin>", line 3
    x = 2
    ^
IndentationError: expected an indented block after 'if' statement in line 2

AttributeError

À l'impression d'une AttributeError, PyErr_Display() offre des suggestions de noms d'attributs similaires dans l'objet pour lequel l'exception a été levée :

>>> collections.namedtoplo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'collections' has no attribute 'namedtoplo'. Did you mean: namedtuple?

(contribution de Pablo Galindo dans bpo-38530).

Avertissement

notez que ceci ne fonctionne pas si PyErr_Display() n'est pas appelée pour afficher l'erreur, ce qui est le cas si une fonction d'affichage d'erreur personnalisée est utilisée. C'est un scénario typique avec certains interpréteurs interactifs comme IPython.

NameError

Quand elle affiche une NameError levée par l'interpréteur, PyErr_Display() offre des suggestions de variables qui ont un nom similaire dans la fonction de laquelle l’exception a été levée :

>>> schwarzschild_black_hole = None
>>> schwarschild_black_hole
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'schwarschild_black_hole' is not defined. Did you mean: schwarzschild_black_hole?

(contribution de Pablo Galindo dans bpo-38530).

Avertissement

notez que ceci ne fonctionne pas si PyErr_Display() n'est pas appelée pour afficher l'erreur, ce qui est le cas si une fonction d'affichage d'erreur personnalisée est utilisée. C'est un scénario typique avec certains interpréteurs interactifs comme IPython.

PEP 626 : numéros de lignes précis pour le débogage et les autres outils

La PEP 626 apporte des numéros de lignes plus précis pour le débogage, le profilage et les outils de mesure de couverture. Les événements de traçage, avec les numéros de ligne corrects, sont générés pour toutes les lignes de code exécutées et seulement pour celles-ci.

The f_lineno attribute of frame objects will always contain the expected line number.

The co_lnotab attribute of code objects is deprecated and will be removed in 3.12. Code that needs to convert from offset to line number should use the new co_lines() method instead.

PEP 634 : filtrage par motifs structurels

Le filtrage par motifs a été ajouté sous la forme d'une instruction match et d'instructions case pour les motifs avec des actions associées. Les motifs filtrent des séquences, des dictionnaires, des types de données et des instances de classes. Le filtrage par motifs permet aux programmes d'extraire de l'information de types de données complexes, faire du branchement selon la structure des données et réaliser des actions spécifiques en fonction des différentes formes des données.

Syntaxe et opérations

La syntaxe générique du filtrage par motifs est :

match subject:
    case <pattern_1>:
        <action_1>
    case <pattern_2>:
        <action_2>
    case <pattern_3>:
        <action_3>
    case _:
        <action_wildcard>

Une instruction match prend une expression et compare successivement sa valeur à différents filtres qui sont donnés comme un ou plusieurs blocs case. Plus précisément, le filtrage par motifs s'effectue par :

  1. l'utilisation de données qui ont un type et une forme (ici subject) ;

  2. l'évaluation de subject dans une instruction match ;

  3. l'application de chaque filtre sur subject dans des instructions case de haut en bas jusqu'à ce qu'un appariement soit confirmé ;

  4. l’exécution de l'action associée au filtre s'il y a appariement ;

  5. s'il n'y a aucun appariement et que le dernier case est un filtre attrape-tout _, l'action correspondante est exécutée. S'il n'y a aucun appariement ni filtre attrape-tout, le bloc match n'effectue aucune opération.

Approche déclarative

Le filtrage par motifs est peut-être connu des lecteurs par l'intermédiaire des langages C, Java ou JavaScript (et plusieurs autres langages), avec l'appariement simple d'un sujet (objet de données) à un littéral (filtre) avec l'instruction switch. Souvent, l'instruction switch est utilisée pour comparer des objets ou expressions à des instructions case qui contiennent des littéraux.

Des exemples plus puissants de filtrage par motifs sont présents dans des langages tels que Scala et Elixir. Avec le filtrage par motifs structurels, l'approche est « déclarative » et énonce les conditions (les motifs) pour apparier les données.

Bien qu'une série d'instructions « impératives » utilisant des instructions « if » imbriquées puisse être utilisée pour accomplir quelque chose de similaire au filtrage par motifs structurels, ceci est moins clair que l'approche « déclarative ». Cette dernière énonce les conditions à remplir pour réaliser un appariement grâce à ses filtres sur des motifs explicites. Bien que le filtrage par motifs structurels puisse être utilisé dans sa forme la plus simple pour comparer une variable à un littéral dans une instruction case, son intérêt réel en Python réside dans son traitement du sujet selon son type et sa forme.

Filtre simple : apparier à un littéral

Regardons cet exemple en tant que filtrage par motif dans sa forme la plus simple : une valeur, le sujet, est comparée à (ou « filtrée par ») plusieurs littéraux, les motifs. Dans l'exemple ci-dessous, status est le sujet de l'instruction match. Les filtres sont chacune des instructions case, où les littéraux représentent les codes de status des requêtes. Les actions associées au case sont exécutés suite à un appariement :

def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"
        case _:
            return "Something's wrong with the internet"

Si on passe 418 à status dans la fonction ci-haut, elle renvoie "I'm a teapot". Avec 500, l'instruction case qui contient _ apparie comme attrape-tout et la fonction renvoie "Something's wrong with the internet". Prenez note que dans le dernier bloc, le nom de variable, _ agit comme un attrape-tout et garantit que le sujet sera toujours apparié. L'utilisation de _ est optionnelle.

Vous pouvez combiner plusieurs littéraux dans un seul filtre en utilisant | (qui se lit « ou ») :

case 401 | 403 | 404:
    return "Not allowed"
Comportement sans l'attrape-tout

Modifions l'exemple ci-haut en enlevant le dernier bloc case. Il devient :

def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"

Sans l'utilisation de _ dans une instruction case, il est possible de ne pas avoir d'appariement. Dans ce cas, il ne se passe rien. Par exemple, si 500 est passé à status, aucune opération n'est effectuée.

Filtres avec un littéral et une variable

Les motifs des filtres peuvent prendre une forme similaire aux affectations multiples et un filtre peut être utilisé pour lier plus d'une variable. Dans cet exemple, un point peut être dissocié entre son abscisse et son ordonnée :

# point is an (x, y) tuple
match point:
    case (0, 0):
        print("Origin")
    case (0, y):
        print(f"Y={y}")
    case (x, 0):
        print(f"X={x}")
    case (x, y):
        print(f"X={x}, Y={y}")
    case _:
        raise ValueError("Not a point")

Le motif du premier filtre comporte deux littéraux, (0, 0), et peut être vu comme une extension du filtre sur un littéral montré plus haut. Les motifs des deux filtres suivants regroupent un littéral et une variable. De plus, la variable est liée à la valeur provenant du sujet (point). Le motif du quatrième filtre capture deux valeurs, ce qui le rend conceptuellement similaire à l'affectation multiple : (x, y) = point.

Filtres et classes

Si vous utilisez des classes pour structurer vos données, vous pouvez utiliser le nom de la classe suivie d'une liste d'arguments comme motif de filtre. Ceci ressemble à un appel du constructeur. Ce filtre peut capturer les attributs de la classe dans des variables :

class Point:
    x: int
    y: int

def location(point):
    match point:
        case Point(x=0, y=0):
            print("Origin is the point's location.")
        case Point(x=0, y=y):
            print(f"Y={y} and the point is on the y-axis.")
        case Point(x=x, y=0):
            print(f"X={x} and the point is on the x-axis.")
        case Point():
            print("The point is located somewhere else on the plane.")
        case _:
            print("Not a point")
Filtres avec arguments positionnels

Vous pouvez utiliser les arguments positionnels avec un certain nombre de classes natives qui définissent l'ordre de leurs attributs, notamment les classes de données (dataclasses). Vous pouvez aussi spécifier la position des attributs quand ils sont utilisés dans les filtres en définissant l'attribut spécial __match_args__ dans vos classes. Par exemple, le mettre à ("x", "y") rend tous les filtres ci-dessous équivalents (en particulier, tous provoquent la liaison de l'attribut y à la variable var) :

Point(1, var)
Point(1, y=var)
Point(x=1, y=var)
Point(y=var, x=1)

Filtres imbriqués

Les filtres peuvent être imbriqués de façon arbitraire. Par exemple, si nous avons une courte liste de points, elle peut être appariée comme ceci :

match points:
    case []:
        print("No points in the list.")
    case [Point(0, 0)]:
        print("The origin is the only point in the list.")
    case [Point(x, y)]:
        print(f"A single point {x}, {y} is in the list.")
    case [Point(0, y1), Point(0, y2)]:
        print(f"Two points on the Y axis at {y1}, {y2} are in the list.")
    case _:
        print("Something else is found in the list.")

Filtres complexes et attrape-tout

Jusqu'à maintenant, les exemples ont utilisé _ seul dans la dernière instruction case. Un attrape-tout peut être utilisé dans un filtre plus complexe tel que ('error', code, _). Par exemple :

match test_variable:
    case ('warning', code, 40):
        print("A warning has been received.")
    case ('error', code, _):
        print(f"An error {code} occurred.")

Dans l'exemple précédent, test_variable s'apparie à ('error', code, 100) et à ('error', code, 800).

Garde

On peut ajouter une clause if à un filtre, ce qu'on appelle une « garde ». Si la garde s'évalue à faux, match poursuit avec la tentative d'appariement du prochain bloc case. Notez que la capture de valeur se produit avant l'évaluation de la garde :

match point:
    case Point(x, y) if x == y:
        print(f"The point is located on the diagonal Y=X at {x}.")
    case Point(x, y):
        print(f"Point is not on the diagonal.")

Autres fonctionnalités importantes

Plusieurs autres fonctionnalités importantes :

  • Comme dans les affectations multiples, les motifs de filtres qui sont des n-uplets ou des listes sont totalement équivalents et autorisent tous les types de séquences. Techniquement, le sujet doit être une séquence. Ainsi, exception importante, les filtres n'autorisent pas les itérateurs. Aussi, pour prémunir d'une erreur commune, les filtres de séquences n'autorisent pas les chaînes ;

  • les filtres de séquence peuvent faire intervenir l'affectation étoilée : [x, y, *reste] ou (x, y, *reste) ont le même sens que dans une affectation avec =. Le nom de variable après l'étoile peut aussi être l'attrape-tout _. Ainsi, (x, y, *_) est un motif de filtre qui reconnaît les séquences à deux éléments ou plus, en capturant les deux premiers et en ignorant le reste ;

  • il existe les filtres d'association, qui ressemblent syntaxiquement aux dictionnaires. Par exemple, le filtre {"bande_passante": b, "latence": l} extrait les valeurs des clés "bande_passante" et "latence" dans un dictionnaire. Contrairement aux filtres de séquence, les clés absentes du filtre sont ignorées et le filtre réussit tout de même. L'affectation double-étoilée (**reste) fonctionne aussi (cependant, **_ serait redondant et n'est donc pas permis) ;

  • on peut capturer la valeur d'une partie du motif d'un filtre avec le mot-clé as, par exemple :

    case (Point(x1, y1), Point(x2, y2) as p2): ...
    

    Ceci lie x1, y1, x2, y2 comme attendu sans la clause as, et lie p2 à l’entièreté du second élément du sujet ;

  • la plupart des littéraux sont comparés par égalité. Néanmoins, les singletons True, False et None sont comparés par identité ;

  • les filtres peuvent contenir des noms qui se réfèrent à des constantes. Ces noms doivent impérativement être qualifiés (contenir au moins un point) pour ne pas être interprétés comme des variables de capture :

    from enum import Enum
    class Color(Enum):
        RED = 0
        GREEN = 1
        BLUE = 2
    
    match color:
        case Color.RED:
            print("I see red!")
        case Color.GREEN:
            print("Grass is green")
        case Color.BLUE:
            print("I'm feeling the blues :(")
    

Pour la spécification complète, voir la PEP 634. La motivation et la justification des choix sont dans la PEP 635, et un tutoriel plus élaboré se trouve dans la PEP 636.

EncodingWarning et option encoding="locale" optionnels

L'encodage par défaut de TextIOWrapper et de open() dépend de la plateforme et des paramètres régionaux. Comme UTF-8 est utilisé sur la plupart des plateformes Unix, ne pas spécifier l'option encoding pour ouvrir des fichiers UTF-8 est une erreur courante. Par exemple :

# BUG: "rb" mode or encoding="utf-8" should be used.
with open("data.json") as f:
    data = json.load(f)

Pour trouver ce type de bogue, un EncodingWarning optionnel a été ajouté. Il est levé quand sys.flags.warn_default_encoding est True et quand l'encodage utilisé est celui défini par les paramètres régionaux.

L'option -X warn_default_encoding et la variable d’environnement PYTHONWARNDEFAULTENCODING ont été ajoutées pour activer cet avertissement.

Voir Encodage de texte pour plus d'informations.

Autres changements au langage

  • Le type int a une nouvelle méthode int.bit_count(), qui renvoie le nombre de chiffres uns dans l’expansion binaire d'un entier donné, aussi connue sous le nom de chiffre de population (population count) (contribution de Niklas Fiekas dans bpo-29882).

  • Les vues renvoyées par dict.keys(), dict.values() et dict.items() ont maintenant toutes un attribut mapping qui donne un objet types.MappingProxyType encapsulant le dictionnaire original (contribution de Dennis Sweeney dans bpo-40890).

  • PEP 618 : la fonction zip() a maintenant un argument optionnel strict, utilisé pour demander que tous les itérables soient de même longueur.

  • Les fonctions d'extensions et les fonctions natives qui prennent des arguments entiers n'acceptent plus les Decimal, Fraction et autres objets qui ne peuvent pas être convertis en entiers sans perte de précision (par exemple ceux qui ont une méthode __int__() mais pas une méthode __index__()) (contribution de Serhiy Storchaka dans bpo-37999).

  • If object.__ipow__() returns NotImplemented, the operator will correctly fall back to object.__pow__() and object.__rpow__() as expected. (Contributed by Alex Shkop in bpo-38302.)

  • Les expressions d'affectations peuvent maintenant être utilisées dans les littéraux d'ensembles, dans les compréhensions d'ensembles et dans les indices de séquences (mais pas dans les tranches).

  • Les fonctions ont un nouvel attribut __builtins__ qui est utilisé pour repérer les symboles natifs quand la fonction est exécutée, plutôt que de regarder dans __globals__['__builtins__']. L'attribut est initialisé à partir de __globals__["__builtins__"] s'il existe, ou des symboles natifs en cours autrement (contribution de Mark Shannon dans bpo-42990).

  • Deux nouvelles fonctions natives – aiter() et anext() – ont été ajoutées pour fournir les équivalents asynchrones de iter() et de next(), respectivement (contribution de Joshua Bronson, Daniel Pope et Justin Wang dans bpo-31861).

  • Les méthodes statiques (@staticmethod) et les méthodes de classes (@classmethod) héritent maintenant des attributs de méthodes (__module__, __name__, __qualname__, __doc__, __annotations__) et ont un nouvel attribut __wrapped__. De plus, les méthodes statiques sont maintenant appelables en tant que fonctions classiques (contribution de Victor Stinner dans bpo-43682).

  • Les annotations des cibles complexes (toutes cibles autre que simple name telles que définies dans la PEP 526) n'ont plus d'effet à l'exécution avec from __future__ import annotations (contribution de Batuhan Taskaya dans bpo-42737).

  • Les objets class et module créent maintenant paresseusement un dictionnaire d'annotations vide sur demande. Les dictionnaires d'annotations sont stockés dans le __dict__ de l'objet pour garder la retro-compatibilité. Cela renforce les bonnes pratiques relatives à __annotations__ ; pour plus d'information, voir Bonnes pratiques concernant les annotations (contribution de Larry Hastings dans bpo-43901).

  • Les annotations qui contiennent yield, yield from, await ou une expression nommée ne sont plus permises sous from __future__ import annotations à cause de leurs effets secondaires (contribution de Batuhan Taskaya dans bpo-42725).

  • L'utilisation de variables non liées, de super() et d'autres expressions qui peuvent changer le traitement de la table des symboles en tant qu'annotation n'ont plus d'effet sous from __future__ import annotations (contribution de Batuhan Taskaya dans bpo-42725).

  • Le hachage des valeurs NaN des types float et decimal.Decimal dépend maintenant de l'identité de l'objet. Préalablement, cette valeur de hachage était toujours 0 alors que les valeurs NaN ne sont pas égales entre elles. Cela pouvait potentiellement entrainer un temps d'exécution quadratique en raison des collisions excessives des valeurs de hachage lors de la création de dictionnaires et d'ensembles qui contiennent plusieurs NaN (contribution de Raymond Hettinger dans bpo-43475).

  • A SyntaxError (instead of a NameError) will be raised when deleting the __debug__ constant. (Contributed by Donghee Na in bpo-45000.)

  • Les exceptions SyntaxError ont maintenant des attributs end_lineno et end_offset. La valeur est None quand ils ne peuvent pas être déterminés (contribution de Pablo Galindo dans bpo-43914).

Nouveaux modules

  • None.

Modules améliorés

asyncio

Ajout de la méthode connect_accepted_socket() manquante (contribution d'Alex Grönholm dans bpo-41332).

argparse

L'expression "optional arguments" qui portait à confusion a été remplacée par "options" dans le message d'aide d'argparse. Certains tests devront être adaptés s'ils dépendent d'une comparaison exacte dans la sortie d'aide (contribution de Raymond Hettinger dans bpo-9694).

array

La méthode index() de la classe array.array a maintenant les paramètres optionnels start et stop (contribution d'Anders Lorentsen et de Zackery Spytz dans bpo-31956).

asynchat, asyncore, smtpd

Ces modules ont étés déclarés obsolètes dans leur documentation de modules depuis Python 3.6. Un DeprecationWarning au moment de l'importation est maintenant ajouté pour ces trois modules.

base64

Ajout de base64.b32hexencode() et de base64.b32hexdecode() pour prendre en charge l'encodage Base32 avec l'alphabet hexadécimal étendu.

bdb

Ajout de clearBreakpoints() pour supprimer tous les points d'arrêt (contribution d'Irit Katriel dans bpo-24160).

bisect

Ajout de la possibilité de fournir une fonction key aux API dans le module bisect (contribution de Raymond Hettinger dans bpo-4356).

codecs

Ajout d'une fonction codecs.unregister() pour désinscrire une fonction de recherche de codecs (contribution de Hai Shi dans bpo-41842).

collections.abc

L'attribut __args__ des génériques paramétrables de collections.abc.Callable est maintenant cohérent avec typing.Callable. Les génériques de collections.abc.Callable aplatissent maintenant les types des paramètres à l'instar de typing.Callable. Ceci veut dire que collections.abc.Callable[[int, str], str] aura un attribut __args__ de valeur (int, str, str) ; auparavant, il aurait été ([int, str], str). Pour permettre ce changement, types.GenericAlias peut être dérivée, et une sous-classe sera renvoyée lors de la surcharge du type collections.abc.Callable. Prenez note que TypeError sera levée pour des formes invalides de paramétrisation de collections.abc.Callable, ce qui aurait pu passer silencieusement dans Python 3.9 (contribution de Ken Jin dans bpo-42195).

contextlib

Ajout d'un gestionnaire de contexte contextlib.aclosing() pour fermer de façon sécurisée les générateurs asynchrones et les objets représentants des ressources libérées de façon asynchrone (contribution de Joongi Kim et John Belmonte dans bpo-41229).

Ajout d'un gestionnaire de contexte pour prendre en charge contextlib.nullcontext() (contribution de Tom Gringauz dans bpo-41543).

Ajout de AsyncContextDecorator pour prendre en charge les gestionnaires de contexte asynchrones en tant que décorateurs.

curses

Les fonctions de couleurs étendues ajoutées dans ncurses 6.1 sont utilisées de façon transparente par curses.color_content(), curses.init_color(), curses.init_pair() et curses.pair_content(). Une nouvelle fonction, curses.has_extended_color_support(), indique si la prise en charge des couleurs étendues est fournie par la bibliothèque ncurses sous-jacente (contribution de Jeffrey Kintscher et de Hans Petter Jansson dans bpo-36982).

Les constantes BUTTON5_* sont maintenant exposées dans le module curses si elles sont fournies par la bibliothèque curses sous-jacente (contribution de Zackery Spytz dans bpo-39273).

dataclasses

__slots__

Ajout du paramètre slots dans le décorateur dataclasses.dataclass() (contribution de Yurii Karabas dans bpo-42269).

Champs obligatoirement nommés

Les classes de données (dataclass) prennent maintenant en charge les champs obligatoirement nommés dans la méthode __init__ générée. Il y a plusieurs façons de spécifier les champs obligatoirement nommés.

Vous pouvez indiquer que tous les champs sont obligatoirement nommés :

from dataclasses import dataclass

@dataclass(kw_only=True)
class Birthday:
    name: str
    birthday: datetime.date

Les paramètres name et birthday sont tous deux obligatoirement nommés dans la méthode __init__ générée.

Pour chaque champ, vous pouvez indiquer s'il est obligatoirement nommé :

from dataclasses import dataclass, field

@dataclass
class Birthday:
    name: str
    birthday: datetime.date = field(kw_only=True)

Ici, seulement birthday est obligatoirement nommé. Si vous assignez kw_only sur un champ particulier, notez qu'il y a des règles concernant l'ordre des champs puisque les champs obligatoirement nommés doivent suivre les champs optionnellement nommés. Voir la documentation de dataclass pour plus de détails.

Vous pouvez aussi indiquer que tous les champs qui suivent un marqueur KW_ONLY sont obligatoirement nommés. Ceci sera probablement l'utilisation la plus commune :

from dataclasses import dataclass, KW_ONLY

@dataclass
class Point:
    x: float
    y: float
    _: KW_ONLY
    z: float = 0.0
    t: float = 0.0

Here, z and t are keyword-only parameters, while x and y are not. (Contributed by Eric V. Smith in bpo-43532.)

distutils

Le paquet distutil est entièrement obsolète et sera retiré dans Python 3.12. Ses fonctionnalités pour spécifier la construction de paquets sont déjà complètement remplacées par les paquets tierce-parties setuptools et packaging. Les autres API régulièrement utilisées sont disponibles ailleurs dans la bibliothèque standard (tel que dans platform, shutil, subprocess ou sysconfig). Il n'est pas prévu de migrer d'autres fonctionnalités de distutils, aussi les applications qui utilisent d'autres fonctions du module doivent faire des copies privées du code. Voir la discussion dans la PEP 632.

La commande bdist_wininst qui est obsolète depuis Python 3.8 a été retirée. La commande bdist_wheel est maintenant recommandée pour distribuer des paquets binaires sous Windows (contribution de Victor Stinner dans bpo-42802).

doctest

Quand un module ne définit pas __loader__, __spec__.loader est utilisé (contribution de Brett Cannon dans bpo-42133).

encodings

La fonction encodings.normalize_encoding() ignore maintenant les caractères non ASCII (contribution de Hai Shi dans bpo-39337).

enum

Enum __repr__() now returns enum_name.member_name and __str__() now returns member_name. Stdlib enums available as module constants have a repr() of module_name.member_name. (Contributed by Ethan Furman in bpo-40066.)

Add enum.StrEnum for enums where all members are strings. (Contributed by Ethan Furman in bpo-41816.)

fileinput

Ajout des paramètres encoding et errors dans fileinput.input() et dans fileinput.FileInput (contribution d'Inada Naoki dans bpo-43712).

fileinput.hook_compressed() renvoie maintenant un objet TextIOWrapper quand mode est "r" et que le fichier est compressé, comme pour les fichiers non compressés (contribution d'Inada Naoki dans bpo-5758).

faulthandler

Le module faulthandler détecte maintenant si une erreur fatale s'est produite pendant un passage du ramasse-miettes (contribution de Victor Stinner dans bpo-44466).

gc

Ajout de fonctions de rappels d'audit pour gc.get_objects(), gc.get_referrers() et gc.get_referents() (contribution de Pablo Galindo dans bpo-43439).

glob

Ajout des paramètres root_dir et dir_fd dans glob() et dans iglob() pour permettre la spécification du répertoire racine utilisé pour la recherche (contribution de Serhiy Storchaka dans bpo-38144).

hashlib

La version minimale d'OpenSSL pour le module hashlib est maintenant 1.1.1 (contribution de Christian Heimes dans PEP 644 et dans bpo-43669).

Le module hashlib offre une prise en charge préliminaire pour OpenSSL 3.0.0 (contribution de Christian Heimes dans bpo-38820 et autres tickets).

Le repli vers la version en pur Python de pbkdf2_hmac() est obsolète. Dorénavant, PBKDF2-HMAC n'est disponible que si Python a été compilé avec la prise en charge d'OpenSSL (contribution de Christian Heimes dans bpo-43880).

hmac

L'implémentation interne du module hmac utilise maintenant HMAC d'OpenSSL (contribution de Christian Heimes dans bpo-40645).

IDLE et idlelib

IDLE invoque maintenant sys.excepthook() (lorsque lancé sans '-n'). Auparavant, les fonctions de rappel définies par l'utilisateur étaient ignorées (contribution par Ken Hilton dans bpo-43008).

Rearrange the settings dialog. Split the General tab into Windows and Shell/Ed tabs. Move help sources, which extend the Help menu, to the Extensions tab. Make space for new options and shorten the dialog. The latter makes the dialog better fit small screens. (Contributed by Terry Jan Reedy in bpo-40468.) Move the indent space setting from the Font tab to the new Windows tab. (Contributed by Mark Roseman and Terry Jan Reedy in bpo-33962.)

Les changements ci-dessus ont été rétro-portés dans le cadre de la maintenance de 3.9.

Ajout d'une barre de côté à la console. Déplacement de l'invite de commande principale (>>>) vers cette barre. Ajout des invites secondaires (...) à la barre de côté. Le clic de gauche et le glisser optionnel sélectionnent une ou plusieurs lignes de texte, tout comme dans la barre de numéros de ligne de la fenêtre d'édition. Le clic droit après la sélection de lignes de texte affiche un menu contextuel pour copier avec invites ('copy with prompts'). Ceci combine les invites de la barre de côté avec le texte sélectionné. Cette option apparait aussi dans le menu contextuel pour le texte (contribution de Tal Einat dans bpo-37903).

Utilisation d'espaces plutôt que des tabulations pour indenter le code interactif. Ceci donne au code interactif la « bonne apparence ». Cette fonctionnalité est fortement corrélée à l'ajout de la barre de côté de la console (contribution de Terry Jan Reedy dans bpo-37892).

Coloration des nouveaux mots clés ad-hoc match, case et _ dans les instructions de filtrage par motifs (pattern matching). Par contre, cette coloration n'est pas parfaite et elle sera incorrecte dans quelques rares cas, y-compris certains _ dans des instructions case (contribution de Tal Einat dans bpo-44010).

Nouveau dans les versions de maintenance 3.10.

Apply syntax highlighting to .pyi files. (Contributed by Alex Waygood and Terry Jan Reedy in bpo-45447.)

Include prompts when saving Shell with inputs and outputs. (Contributed by Terry Jan Reedy in gh-95191.)

importlib.metadata

Équivalence de fonctionnalités avec importlib_metadata 4.6 (historique).

Les points d'entrée de importlib.metadata offrent maintenant une interface plus agréable pour choisir les points d'entrée par groupe et par nom par l'intermédiaire d'une nouvelle classe importlib.metadata.EntryPoints. Voir la rubrique Note sur la Compatibilité (Compatibility Note) dans la documentation du module importlib.metadata pour plus d'information sur son utilisation et ce qui devient obsolète.

Ajout de importlib.metadata.packages_distributions() pour résoudre les modules et paquets Python du niveau racine vers leur importlib.metadata.Distribution.

inspect

Quand un module ne définit pas __loader__, __spec__.loader est utilisé (contribution de Brett Cannon dans bpo-42133).

Ajout de inspect.get_annotations() qui calcule les annotations définies sur un objet de façon sécuritaire. Elle contourne les difficultés d’accéder aux annotations de différents types d'objets et présume très peu de l'objet examiné. inspect.get_annotations() peut également convertir pour vous les annotations contenues dans des chaînes de caractères en objets. inspect.get_annotations() est maintenant considérée comme la meilleure pratique pour accéder au dictionnaire d'annotations de tout objet qui prend en charge les annotations ; pour d'autre information sur les meilleures pratiques relatives aux annotations, voir Bonnes pratiques concernant les annotations. Dans le même esprit, inspect.signature(), inspect.Signature.from_callable() et inspect.Signature.from_function() appellent maintenant inspect.get_annotations() pour récupérer les annotations. Ceci veut dire que inspect.signature() et inspect.Signature.from_callable() peuvent maintenant convertir pour vous les annotations contenues dans des chaînes de caractères en objets (contribution de Larry Hastings dans bpo-43817).

itertools

Add itertools.pairwise(). (Contributed by Raymond Hettinger in bpo-38200.)

linecache

Quand un module ne définit pas __loader__, __spec__.loader est utilisé (contribution de Brett Cannon dans bpo-42133).

os

Ajout de la prise en charge de VxWorks RTOS dans os.cpu_count() (contribution de Peixing Xin dans bpo-41440).

Ajout d'une nouvelle fonction os.eventfd() et des fonctions utilitaires associées pour encapsuler l'appel système eventfd2 sur Linux (contribution de Christian Heimes dans bpo-41001).

Ajout de os.splice() qui permet de déplacer des données entre deux descripteurs de fichiers sans copie entre les espaces noyau et utilisateur. Un des descripteurs de fichiers doit référencer un tube (pipe) (contribution de Pablo Galindo dans bpo-41625).

Add O_EVTONLY, O_FSYNC, O_SYMLINK and O_NOFOLLOW_ANY for macOS. (Contributed by Donghee Na in bpo-43106.)

os.path

os.path.realpath() accepte maintenant l'argument nommé strict. Lorsqu'il est True, une OSError est levée si le chemin n'existe pas ou si une boucle de liens symboliques est rencontrée (contribution de Barney Gale dans bpo-43757).

pathlib

Add slice support to PurePath.parents. (Contributed by Joshua Cannon in bpo-35498.)

Add negative indexing support to PurePath.parents. (Contributed by Yaroslav Pankovych in bpo-21041.)

Ajout de la méthode Path.hardlink_to qui remplace link_to(). L'ordre des arguments de la nouvelle méthode est le même que symlink_to() (contribution de Barney Gale dans bpo-39950).

pathlib.Path.stat() et chmod() acceptent maintenant l'argument nommé follow_symlinks pour rester cohérent avec les fonctions correspondantes dans le module os (contribution de Barney Gale dans bpo-39906).

platform

Add platform.freedesktop_os_release() to retrieve operation system identification from freedesktop.org os-release standard file. (Contributed by Christian Heimes in bpo-28468.)

pprint

pprint.pprint() accepte maintenant le nouvel argument nommé underscore_numbers (contribution de sblondon dans bpo-42914).

pprint peut maintenant afficher élégamment les instances de dataclasses.dataclass (contribution de Lewis Gaul dans bpo-43080).

py_compile

Ajout de l'option de ligne de commande --quiet à l'interface de py_compile (contribution de Gregory Schevchenko dans bpo-38731).

pyclbr

Add an end_lineno attribute to the Function and Class objects in the tree returned by pyclbr.readmodule() and pyclbr.readmodule_ex(). It matches the existing (start) lineno. (Contributed by Aviral Srivastava in bpo-38307.)

shelve

The shelve module now uses pickle.DEFAULT_PROTOCOL by default instead of pickle protocol 3 when creating shelves. (Contributed by Zackery Spytz in bpo-34204.)

statistics

Ajout des fonctions covariance(), correlation() (corrélation de Pearson) et linear_regression() (régression linéaire simple) (contribution de Tymoteusz Wołodźko dans bpo-38490).

site

Quand un module ne définit pas __loader__, __spec__.loader est utilisé (contribution de Brett Cannon dans bpo-42133).

socket

L'exception socket.timeout est maintenant un alias de TimeoutError (contribution de Christian Heimes dans bpo-42413).

Ajout d'une option pour créer des connecteurs (socket) MPTCP avec IPPROTO_MPTCP (contribution de Rui Cunha dans bpo-43571).

Ajout de l'option IP_RECVTOS pour récupérer la valeur des champs type of service (ToS) ou differentiated services code point (DSCP/ECN) (contribution de Georg Sauthoff dans bpo-44077).

ssl

La version minimale d'OpenSSL pour le module ssl est maintenant 1.1.1 (contribution de Christian Heimes dans PEP 644 et dans bpo-43669).

The ssl module has preliminary support for OpenSSL 3.0.0 and new option OP_IGNORE_UNEXPECTED_EOF. (Contributed by Christian Heimes in bpo-38820, bpo-43794, bpo-43788, bpo-43791, bpo-43799, bpo-43920, bpo-43789, and bpo-43811.)

Les fonctions obsolètes et l'accès aux constantes obsolètes lèvent maintenant un DeprecationWarning. ssl.SSLContext.options a options OP_NO_SSLv2 et OP_NO_SSLv3 définies par défaut ; par conséquent, il ne peut pas avertir si l'option est définie de nouveau. La section obsolescence contient la liste des fonctionnalités obsolètes (contribution de Christian Heimes dans bpo-43880).

La configuration du module ssl est plus sécuritaire par défaut. Les algorithmes de chiffrement sans confidentialité persistante (forward secrecy) et le code d'authentification de message (MAC) SHA-1 sont désactivés par défaut. Le niveau 2 de sécurité ne permet pas les clés faibles de moins de 112 bits pour RSA, DH et ECC. La version minimale du protocole TLS pour SSLContext est 1.2. La configuration est basée sur la recherche de Hynek Schlawack (contribution de Christian Heimes dans bpo-43998).

Les protocoles obsolètes SSL 3.0, TLS 1.0 et TLS 1.1 ne sont plus officiellement pris en charge. Python ne les bloque pas activement, mais les options de compilation d'OpenSSL, les configurations du système d'exploitation, les rustines des fabricants et les suites d'algorithmes de chiffrement peuvent empêcher l’établissement d'une connexion.

Ajout d'un paramètre timeout à la fonction ssl.get_server_certificate() (contribution de Zackery Spytz dans bpo-31870).

Le module ssl utilise les types du tas et l'initialisation multi-phase (contribution de Christian Heimes dans bpo-42333).

A new verify flag VERIFY_X509_PARTIAL_CHAIN has been added. (Contributed by l0x in bpo-40849.)

sqlite3

Ajout d'événements d'audit pour connect/handle(), enable_load_extension() et load_extension() (contribution d'Erlend E. Aasland dans bpo-43762).

sys

Ajout de l'attribut sys.orig_argv : la liste des arguments de ligne de commande originalement passée à l'exécutable Python (contribution de Victor Stinner dans bpo-23427).

Ajout de sys.stdlib_module_names qui contient la liste des noms des modules de la bibliothèque standard (contribution de Victor Stinner dans bpo-42955).

_thread

_thread.interrupt_main() now takes an optional signal number to simulate (the default is still signal.SIGINT). (Contributed by Antoine Pitrou in bpo-43356.)

threading

Ajout des fonctions threading.gettrace() et threading.getprofile() pour récupérer les fonctions assignées par threading.settrace() et threading.setprofile() respectivement (contribution de Mario Corchero dans bpo-42251).

Ajout de threading.__excepthook__ pour permettre la récupération de threading.excepthook() au cas où elle serait affectée à une valeur incorrecte ou différente (contribution de Mario Corchero dans bpo-42308).

traceback

Les fonctions format_exception(), format_exception_only() et print_exception() peuvent maintenant prendre un objet exception en argument positionnel (contribution de Zackery Spytz et Matthias Bussonnier dans bpo-26389).

types

Les classes types.EllipsisType, types.NoneType et types.NotImplementedType sont ajoutées de nouveau. Elles fournissent un nouvel ensemble de types facilement interprétable par les vérificateurs de types (contribution de Bas van Beek dans bpo-41810).

typing

Pour les changements majeurs, voir Nouvelles fonctionnalités reliées aux indications de types.

Le comportement de typing.Literal a été changé pour être conforme avec la PEP 586 et pour correspondre au comportement des vérificateurs de types statiques défini dans la PEP.

  1. Literal dé-duplique maintenant les paramètres.

  2. La comparaison d'égalité entre objets Literal ne tient plus compte de l'ordre.

  3. Les comparaisons de Literal respectent maintenant les types. Par exemple, Literal[0] == Literal[False] était préalablement évaluée à True. Elle est maintenant False. Pour prendre en charge ce changement, le cache des types de l'implémentation interne peut maintenant différencier entre les types.

  4. Les objets Literal lèvent maintenant une exception TypeError pendant la comparaison d'égalité si au moins un de leurs paramètres n'est pas hachable. Notez que déclarer un Literal avec des paramètres non hachables ne lève pas d'erreur :

    >>> from typing import Literal
    >>> Literal[{0}]
    >>> Literal[{0}] == Literal[{False}]
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unhashable type: 'set'
    

(contribution de Yurii Karabas dans bpo-42345).

Add new function typing.is_typeddict() to introspect if an annotation is a typing.TypedDict. (Contributed by Patrick Reader in bpo-41792.)

Subclasses of typing.Protocol which only have data variables declared will now raise a TypeError when checked with isinstance unless they are decorated with runtime_checkable(). Previously, these checks passed silently. Users should decorate their subclasses with the runtime_checkable() decorator if they want runtime protocols. (Contributed by Yurii Karabas in bpo-38908.)

Importing from the typing.io and typing.re submodules will now emit DeprecationWarning. These submodules have been deprecated since Python 3.8 and will be removed in a future version of Python. Anything belonging to those submodules should be imported directly from typing instead. (Contributed by Sebastian Rittau in bpo-38291.)

unittest

Ajout d'une nouvelle méthode assertNoLogs() pour complémenter la méthode existante assertLogs() (contribution de Kit Yan Choi dans bpo-39385).

urllib.parse

Les versions préalables à Python 3.10 acceptaient les deux caractères ; et & comme séparateurs de paramètres de requêtes dans urllib.parse.parse_qs() et urllib.parse.parse_qsl(). Pour prévenir des failles de sécurité potentielles et pour respecter les dernières recommandations du W3C, ceci a été changé pour ne permettre qu'une seule clé de séparation, avec & par défaut. Ce changement affecte aussi l'implémentation interne de cgi.parse() et de cgi.parse_multipart() puisqu'elles utilisent les fonctions affectées. Pour plus de détails, voir la documentation respective de ces fonctions (contribution d'Adam Goldschmidt, de Senthil Kumaran et de Ken Jin dans bpo-42967).

The presence of newline or tab characters in parts of a URL allows for some forms of attacks. Following the WHATWG specification that updates RFC 3986, ASCII newline \n, \r and tab \t characters are stripped from the URL by the parser in urllib.parse preventing such attacks. The removal characters are controlled by a new module level variable urllib.parse._UNSAFE_URL_BYTES_TO_REMOVE. (See gh-88048)

xml

Ajout d'une classe LexicalHandler au module xml.sax.handler (contribution de Jonathan Gossage de Zackery Spytz dans bpo-35018).

zipimport

Ajout des méthodes relatives à la PEP 451 : find_spec(), zipimport.zipimporter.create_module() et zipimport.zipimporter.exec_module() (contribution de Brett Cannon dans bpo-42131).

Ajout de la méthode invalidate_caches() (contribution de Desmond Cheong dans bpo-14678).

Optimisations

  • Les constructeurs de str(), bytes() et bytearray() sont maintenant plus rapides (environ 30—40 % pour les petits objets) (contribution de Serhiy Storchaka dans bpo-41334).

  • Le module runpy importe maintenant moins de modules. Le temps de démarrage de la commande python3 -m module-name est en moyenne 1,4 fois plus rapide. Sur Linux python3 -I -m module-name importe 69 modules dans Python 3.9, alors qu'elle n'en importe que 51 (18 de moins) dans Python 3.10 (contribution de Victor Stinner dans bpo-41006 et dans bpo-41718).

  • L'instruction LOAD_ATTR utilise maintenant le mécanisme de cache par code d'opération. Elle est environ 36 % plus rapide pour les attributs ordinaires et 44 % plus rapide pour les slots (contribution de Pablo Galindo et de Yury Selivanov dans bpo-42093 et Guido van Rossum dans bpo-42927, basée sur des idées originalement mises en œuvre dans PyPy et dans MicroPython).

  • Lors de la construction de Python avec --enable-optimizations, -fno-semantic-interposition est maintenant ajouté aux lignes de commande de compilation et d'édition des liens. Ceci accélère les binaires de l'interpréteur Python créés avec --enable-shared et gcc jusqu'à 30 %. Voir cet article (en anglais) pour plus de détails (contribution de Victor Stinner et Pablo Galindo dans bpo-38980).

  • Ré-usinage du code assurant la gestion du tampon de sortie pour les modules bz2, lzma et zlib. Ajout de la fonction .readall() à la classe _compression.DecompressReader. La décompression bz2 est 1,09 à 1,17 fois plus rapide, la décompression lzma est 1,20 à 1,32 fois plus rapide, GzipFile.read(-1) est 1,11 à 1,18 fois plus rapide (contribution de Ma Lin, révision par Gregory P. Smith dans bpo-41486).

  • When using stringized annotations, annotations dicts for functions are no longer created when the function is created. Instead, they are stored as a tuple of strings, and the function object lazily converts this into the annotations dict on demand. This optimization cuts the CPU time needed to define an annotated function by half. (Contributed by Yurii Karabas and Inada Naoki in bpo-42202.)

  • Les fonctions de recherche de sous-chaînes telles que str1 in str2 et str2.find(str1) peuvent utiliser maintenant l'algorithme « bidirectionnel » de recherche de chaînes Crochemore et Perrin pour éviter le comportement quadratique sur les longues chaînes (contribution de Dennis Sweeney dans bpo-41972).

  • Add micro-optimizations to _PyType_Lookup() to improve type attribute cache lookup performance in the common case of cache hits. This makes the interpreter 1.04 times faster on average. (Contributed by Dino Viehland in bpo-43452.)

  • The following built-in functions now support the faster PEP 590 vectorcall calling convention: map(), filter(), reversed(), bool() and float(). (Contributed by Donghee Na and Jeroen Demeyer in bpo-43575, bpo-43287, bpo-41922, bpo-41873 and bpo-41870.)

  • BZ2File performance is improved by removing internal RLock. This makes BZ2File thread unsafe in the face of multiple simultaneous readers or writers, just like its equivalent classes in gzip and lzma have always been. (Contributed by Inada Naoki in bpo-43785.)

Obsolescence

Retrait

  • Les méthodes spéciales __int__, __float__, __floordiv__, __mod__, __divmod__, __rfloordiv__, __rmod__ et __rdivmod__ sont retirées de la classe complex. Elles levaient toujours une TypeError (contribution de Serhiy Storchaka dans bpo-41974).

  • La méthode ParserBase.error() du module privé et non-documenté _markupbase a été retirée. html.parser.HTMLParser est la seule sous-classe de ParserBase et son implémentation de la méthode error() a été retirée dans Python 3.5 (contribution de Berker Peksag dans bpo-31844).

  • Retrait de l'attribut unicodedata.ucnhash_CAPI qui était un objet PyCapsule interne. La structure privée associée _PyUnicode_Name_CAPI a été déplacée vers l'API C interne (contribution de Victor Stinner dans bpo-42157).

  • Retrait du module parser qui était obsolète depuis 3.9 étant donné la transition vers le nouvel analyseur syntaxique PEG. Retrait aussi des fichiers source et en-tête C qui n'étaient utilisés que par l'ancien analyseur, ceci comprend node.h, parser.h, graminit.h et grammar.h.

  • Retrait des fonctions PyParser_SimpleParseStringFlags, PyParser_SimpleParseStringFlagsFilename, PyParser_SimpleParseFileFlags et PyNode_Compile de l'API C publique. Elles étaient obsolètes depuis 3.9 étant donné la transition vers l'analyseur syntaxique PEG.

  • Removed the formatter module, which was deprecated in Python 3.4. It is somewhat obsolete, little used, and not tested. It was originally scheduled to be removed in Python 3.6, but such removals were delayed until after Python 2.7 EOL. Existing users should copy whatever classes they use into their code. (Contributed by Donghee Na and Terry J. Reedy in bpo-42299.)

  • Removed the PyModule_GetWarningsModule() function that was useless now due to the _warnings module was converted to a builtin module in 2.6. (Contributed by Hai Shi in bpo-42599.)

  • Retrait des alias obsolètes Classes de base abstraites de collections du module collections (contribution de Victor Stinner dans bpo-37324).

  • Le paramètre loop a été retiré de la majorité de l'API haut-niveau d'asyncio. Il était obsolète depuis Python 3.8. La motivation pour ce changement avait plusieurs facettes :

    1. ceci simplifie l'API haut-niveau ;

    2. les fonctions dans l'API haut niveau reçoivent implicitement la boucle d'évènements qui tourne dans le présent fil d'exécution depuis Python 3.7. Il n'y a aucun besoin de passer la boucle d'évènements à l'API dans la majorité de son utilisation normale ;

    3. le passage de la boucle d'évènements cause facilement des erreurs quand plusieurs boucles qui tournent dans plusieurs fils d'exécution sont impliquées.

    Prenez note que l'API bas-niveau accepte toujours le paramètre loop. Voir Changements dans l'API Python pour plus d'exemples sur comment remplacer le code existant

    (contribution de Yurii Karabas, Andrew Svetlov, Yury Selivanov et Kyle Stanley dans bpo-42392).

Portage vers Python 3.10

Cette section liste les changements mentionnés préalablement et autres améliorations qui peuvent demander des changements à votre code.

Changements à la syntaxe de Python

  • Deprecation warning is now emitted when compiling previously valid syntax if the numeric literal is immediately followed by a keyword (like in 0in x). In future releases it will be changed to syntax warning, and finally to a syntax error. To get rid of the warning and make the code compatible with future releases just add a space between the numeric literal and the following keyword. (Contributed by Serhiy Storchaka in bpo-43833.)

Changements dans l'API Python

  • Les paramètres etype des fonctions format_exception(), format_exception_only() et print_exception() du module traceback ont étés renommés exc (contribution de Zackery Spytz et Matthias Bussonnier dans bpo-26389).

  • atexit : à la fin de l'exécution de Python, si une fonction de rappel qui a été enregistrée avec atexit.register() échoue, son exception est maintenant journalisée. Préalablement, seulement certaines exceptions étaient journalisées et la dernière exception était toujours ignorée de façon silencieuse (contribution de Victor Stinner dans bpo-42639).

  • Les génériques de collections.abc.Callable aplatissent maintenant les paramètres de types tel qu'il est fait par typing.Callable. Ceci veut dire que collections.abc.Callable[[int, str], str] aura un attribut __args__ de valeur (int, str, str) ; préalablement, il aurait été ([int, str], str). Les codes qui accèdent aux arguments par typing.get_args() ou __args__ doivent tenir compte de ce changement. De plus, TypeError sera levée pour des formes invalides de paramétrisation de collections.abc.Callable, ce qui aurait pu passer silencieusement dans Python 3.9 (contribution de Ken Jin dans bpo-42195).

  • socket.htons() et socket.ntohs() lèvent maintenant OverflowError plutôt que DeprecationWarning si le paramètre passé est trop grand pour être stocké dans un entier 16-bit non-signé (contribution de Erlend E. Aasland dans bpo-42393).

  • Le paramètre loop a été retiré de la majorité de l'API haut-niveau d'asyncio suite à la déclaration de son obsolescence dans Python 3.8.

    Une coroutine qui ressemble actuellement à ceci :

    async def foo(loop):
        await asyncio.sleep(1, loop=loop)
    

    Doit être remplacée par ceci :

    async def foo():
        await asyncio.sleep(1)
    

    Si foo() a été spécifiquement conçue pour ne pas s'exécuter dans le fil d'exécution courant, (par exemple pour tourner dans la boucle d'exécution d'un autre fil), l'utilisation de asyncio.run_coroutine_threadsafe() est probablement plus appropriée.

    (contribution de Yurii Karabas, Andrew Svetlov, Yury Selivanov et Kyle Stanley dans bpo-42392).

  • Le constructeur de types.FunctionType hérite maintenant des définitions natives si le dictionnaire globals n'a pas de clé "__builtins__", plutôt que d'utiliser {"None": None} pour les définitions natives : même comportement que celui des fonctions eval() et exec(). Définir une fonction avec def function(...): ... en Python n'est pas affecté, les globales ne peuvent pas être changées avec cette syntaxe : elles héritent aussi des définitions natives courantes (contribution de Victor Stinner dans bpo-42990).

Changements dans l'API C

  • Les fonctions de l'API C PyParser_SimpleParseStringFlags, PyParser_SimpleParseStringFlagsFilename, PyParser_SimpleParseFileFlags et PyNode_Compile ainsi que struct _node, le type utilisé par ces fonctions, ont été retirés suite à la transition vers le nouvel analyseur syntaxique PEG.

    Le code source doit maintenant être compilé directement en un objet code, en utilisant par exemple Py_CompileString(). L'objet code ainsi produit peut ensuite être évalué, en utilisant par exemple PyEval_EvalCode().

    Spécifiquement :

    • Un appel à PyParser_SimpleParseStringFlags suivi de PyNode_Compile peut être remplacé par Py_CompileString() ;

    • Il n'y a pas de remplacement immédiat pour PyParser_SimpleParseFileFlags. Pour compiler du code à partir d'un argument FILE *, vous devez lire le fichier en C et passer le tampon résultant à Py_CompileString().

    • Pour compiler un fichier à partir du char * de son nom, ouvrez le fichier de façon explicite, lisez son contenu et compilez le résultat. Une façon de faire est d'utiliser le module io en conjonction avec PyImport_ImportModule(), PyObject_CallMethod(), PyBytes_AsString() et Py_CompileString(), comme dans l'esquisse qui suit (les déclarations et la gestion d'erreurs ne sont pas incluses)

      io_module = Import_ImportModule("io");
      fileobject = PyObject_CallMethod(io_module, "open", "ss", filename, "rb");
      source_bytes_object = PyObject_CallMethod(fileobject, "read", "");
      result = PyObject_CallMethod(fileobject, "close", "");
      source_buf = PyBytes_AsString(source_bytes_object);
      code = Py_CompileString(source_buf, filename, Py_file_input);
      
    • For FrameObject objects, the f_lasti member now represents a wordcode offset instead of a simple offset into the bytecode string. This means that this number needs to be multiplied by 2 to be used with APIs that expect a byte offset instead (like PyCode_Addr2Line() for example). Notice as well that the f_lasti member of FrameObject objects is not considered stable: please use PyFrame_GetLineNumber() instead.

Changements au code intermédiaire CPython

  • The MAKE_FUNCTION instruction now accepts either a dict or a tuple of strings as the function's annotations. (Contributed by Yurii Karabas and Inada Naoki in bpo-42202.)

Changements à la compilation

  • PEP 644 : la version minimale d'OpenSSL pour Python est maintenant 1.1.1. OpenSSL 1.0.2 n'est plus prise en charge (contribution de Christian Heimes dans bpo-43669).

  • Les fonctions de C99 snprintf() et vsnprintf() sont maintenant nécessaires à la compilation de Python (contribution de Victor Stinner dans bpo-36020).

  • La version minimale de SQLite pour le module sqlite3 est maintenant 3.7.15 (contribution de Sergey Fedoseev et Erlend E. Aasland dans bpo-40744 et bpo-40810).

  • Le module atexit doit maintenant toujours être compilé en tant que module natif (contribution de Victor Stinner dans bpo-42639).

  • Ajout de l'option --disable-test-modules au script configure : ne pas compiler ni installer les modules de tests (contribution de Xavier de Gaye, Thomas Petazzoni et Peixing Xin dans bpo-27640).

  • Ajout de l'option --with-wheel-pkg-dir=PATH au script ./configure. Si elle est passée, le module ensurepip recherche les paquets wheel de setuptools et de pip dans ce répertoire : si les deux sont présents, ces paquets wheel sont utilisés plutôt que ceux inclus avec ensurepip.

    La politique de paquets de certaines distributions Linux déconseille l'inclusion des dépendances. Par exemple, Fedora installe les paquets wheel dans le répertoire /usr/share/python-wheels/ et n'installe pas le paquet ensurepip._bundled

    (contribution de Victor Stinner dans bpo-42856).

  • Ajout d'une nouvelle option --without-static-libpython au script configure pour ne pas compiler la bibliothèque statique libpythonMAJOR.MINOR.a et ne pas installer le fichier objet python.o

    (contribution de Victor Stinner dans bpo-43103).

  • The configure script now uses the pkg-config utility, if available, to detect the location of Tcl/Tk headers and libraries. As before, those locations can be explicitly specified with the --with-tcltk-includes and --with-tcltk-libs configuration options. (Contributed by Manolis Stamatogiannakis in bpo-42603.)

  • Ajout de l'option --with-openssl-rpath au script configure. Cette option simplifie la compilation de Python avec une installation personnalisée d'OpenSSL, par exemple : ./configure --with-openssl=/path/to/openssl --with-openssl-rpath=auto (contribution de Christian Heimes dans bpo-43466).

Changements à l'API C

PEP 652 : maintenance d'une ABI stable

L'interface binaire-programme (Application Binary Interface, ABI en anglais) stable pour les modules d'extension ou pour l'intégration de Python est maintenant définie de façon explicite. Le document Stabilité de l’API C décrit les garanties de stabilité pour l'API C et pour l'interface binaire-programme ainsi que les bonnes pratiques pour travailler avec l'interface binaire-programme stable

(contribution de Petr Viktorin dans PEP 652 et dans bpo-43795).

Nouvelles fonctionnalités

Portage vers Python 3.10

  • The PY_SSIZE_T_CLEAN macro must now be defined to use PyArg_ParseTuple() and Py_BuildValue() formats which use #: es#, et#, s#, u#, y#, z#, U# and Z#. See Analyse des arguments et construction des valeurs and PEP 353. (Contributed by Victor Stinner in bpo-40943.)

  • Étant donné la conversion de Py_REFCNT() en fonction statique en-ligne, Py_REFCNT(obj) = new_refcnt doit être remplacé par Py_SET_REFCNT(obj, new_refcnt) : voir Py_SET_REFCNT() (disponible depuis Python 3.9). Pour la rétro-compatibilité, cette macro peut être utilisée :

    #if PY_VERSION_HEX < 0x030900A4
    #  define Py_SET_REFCNT(obj, refcnt) ((Py_REFCNT(obj) = (refcnt)), (void)0)
    #endif
    

    (contribution de Victor Stinner dans bpo-39573).

  • Appeler PyDict_GetItem() sans avoir obtenu le GIL était autorisé pour des raisons historiques. Ceci n'est plus permis (contribution de Victor Stinner dans bpo-40839).

  • PyUnicode_FromUnicode(NULL, size) et PyUnicode_FromStringAndSize(NULL, size) lèvent maintenant un DeprecationWarning. Vous devez utiliser PyUnicode_New() pour allouer un objet Unicode sans donnée initiale (contribution de Inada Naoki dans bpo-36346).

  • La structure privée _PyUnicode_Name_CAPI de l'API PyCapsule unicodedata.ucnhash_CAPI a été déplacée dans l'API C interne. (Contribution par Victor Stinner dans bpo-42157.)

  • Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix(), Py_GetProgramFullPath(), Py_GetPythonHome() and Py_GetProgramName() functions now return NULL if called before Py_Initialize() (before Python is initialized). Use the new Python Initialization Configuration API to get the Python Path Configuration. (Contributed by Victor Stinner in bpo-42260.)

  • PyList_SET_ITEM(), PyTuple_SET_ITEM() and PyCell_SET() macros can no longer be used as l-value or r-value. For example, x = PyList_SET_ITEM(a, b, c) and PyList_SET_ITEM(a, b, c) = x now fail with a compiler error. It prevents bugs like if (PyList_SET_ITEM (a, b, c) < 0) ... test. (Contributed by Zackery Spytz and Victor Stinner in bpo-30459.)

  • The non-limited API files odictobject.h, parser_interface.h, picklebufobject.h, pyarena.h, pyctype.h, pydebug.h, pyfpe.h, and pytime.h have been moved to the Include/cpython directory. These files must not be included directly, as they are already included in Python.h; see Include Files. If they have been included directly, consider including Python.h instead. (Contributed by Nicholas Sim in bpo-35134.)

  • Use the Py_TPFLAGS_IMMUTABLETYPE type flag to create immutable type objects. Do not rely on Py_TPFLAGS_HEAPTYPE to decide if a type object is mutable or not; check if Py_TPFLAGS_IMMUTABLETYPE is set instead. (Contributed by Victor Stinner and Erlend E. Aasland in bpo-43908.)

  • The undocumented function Py_FrozenMain has been removed from the limited API. The function is mainly useful for custom builds of Python. (Contributed by Petr Viktorin in bpo-26241.)

Obsolescence

  • La fonction PyUnicode_InternImmortal() est maintenant obsolète et sera retirée dans Python 3.12 : utilisez plutôt PyUnicode_InternInPlace() (contribution de Victor Stinner dans bpo-41692).

Retrait

  • Retrait des fonctions Py_UNICODE_str* manipulant des chaînes Py_UNICODE* (contribution de Inada Naoki dans bpo-41123) :

  • Retrait de PyUnicode_GetMax(). Vous devez migrer vers les nouvelles API de la PEP 393 (contribution de Inada Naoki dans bpo-41103).

  • Retrait de PyLong_FromUnicode(). Vous devez migrer vers PyLong_FromUnicodeObject() (contribution de Inada Naoki dans bpo-41103).

  • Retrait de PyUnicode_AsUnicodeCopy(). Vous devez utiliser PyUnicode_AsUCS4Copy() ou PyUnicode_AsWideCharString() (contribution de Inada Naoki dans bpo-41103).

  • Retrait de la variable _Py_CheckRecursionLimit : elle a été remplacée par le champ ceval.recursion_limit de la structure PyInterpreterState (contribution de Victor Stinner dans bpo-41834).

  • Retrait des macros non-documentées Py_ALLOW_RECURSION et Py_END_ALLOW_RECURSION et du champ recursion_critical de la structure PyInterpreterState (contribution de Serhiy Storchaka dans bpo-41936).

  • Retrait de la fonction non-documentée PyOS_InitInterrupts(). L'initialisation de Python installe déjà les gestionnaires de signaux de façon implicite : voir PyConfig.install_signal_handlers (contribution de Victor Stinner dans bpo-41713).

  • Retrait de la fonction PyAST_Validate(). Il n'est plus possible de construire un objet AST (type mod_ty) avec l'API C publique. La fonction était déjà retirée de l'API C limitée (PEP 384) (contribution de Victor Stinner dans bpo-43244).

  • Retrait du fichier d'en-tête symtable.h et des fonctions non-documentées :

    • PyST_GetScope() ;

    • PySymtable_Build() ;

    • PySymtable_BuildObject() ;

    • PySymtable_Free() ;

    • Py_SymtableString() ;

    • Py_SymtableStringObject().

    Par erreur, la fonction Py_SymtableString() faisait partie de l'ABI stable, mais elle ne pouvait pas être utilisée, car le fichier d'en-tête symtable.h était exclu de l'API C limitée.

    Utilisez plutôt le module Python symtable (contribution de Victor Stinner dans bpo-43244).

  • Retrait de PyOS_ReadlineFunctionPointer() des fichiers d'en-tête de l'API C limitée et de python3.dll, la bibliothèque qui fournit l'ABI stable sur Windows. Étant donné que la fonction prend un FILE* en argument, la stabilité de son interface binaire-programme ne peut pas être garantie (contribution de Petr Viktorin dans bpo-43868).

  • Retrait des fichiers d'en-tête ast.h, asdl.h et Python-ast.h. Ces fonctions étaient non-documentées et exclues de l'API C limitée. La majorité des noms définis dans ces fichiers d'en-tête n'avaient pas le préfixe Py et pouvaient ainsi causer des conflits de noms. Par exemple, Python-ast.h définit une macro Yield qui était en conflit avec le nom Yield utilisé dans le fichier d'en-tête <winbase.h> de Windows. Utilisez plutôt le module Python ast (contribution de Victor Stinner dans bpo-43244).

  • Retrait des fonctions d'analyse syntaxique et de compilation qui utilisent le type struct _mod car l'API C publique pour manipuler les AST a été retirée :

    • PyAST_Compile() ;

    • PyAST_CompileEx() ;

    • PyAST_CompileObject() ;

    • PyFuture_FromAST() ;

    • PyFuture_FromASTObject() ;

    • PyParser_ASTFromFile() ;

    • PyParser_ASTFromFileObject() ;

    • PyParser_ASTFromFilename() ;

    • PyParser_ASTFromString() ;

    • PyParser_ASTFromStringObject().

    Ces fonctions étaient non-documentées et exclues de l'API C limitée (contribution de Victor Stinner dans bpo-43244).

  • Retrait du fichier d'en-tête pyarena.h et des fonctions :

    • PyArena_New() ;

    • PyArena_Free() ;

    • PyArena_Malloc() ;

    • PyArena_AddPyObject().

    Ces fonctions étaient non-documentées et exclues de l'API C limitée ; elles n'étaient utilisées que par le compilateur dans l'implémentation interne (contribution de Victor Stinner dans bpo-43244).

  • Retrait du champ PyThreadState.use_tracing pour optimiser Python (contribution de Mark Shannon dans bpo-43760).

Notable security feature in 3.10.7

Converting between int and str in bases other than 2 (binary), 4, 8 (octal), 16 (hexadecimal), or 32 such as base 10 (decimal) now raises a ValueError if the number of digits in string form is above a limit to avoid potential denial of service attacks due to the algorithmic complexity. This is a mitigation for CVE-2020-10735. This limit can be configured or disabled by environment variable, command line flag, or sys APIs. See the integer string conversion length limitation documentation. The default limit is 4300 digits in string form.

Notable security feature in 3.10.8

The deprecated mailcap module now refuses to inject unsafe text (filenames, MIME types, parameters) into shell commands. Instead of using such text, it will warn and act as if a match was not found (or for test commands, as if the test failed). (Contributed by Petr Viktorin in gh-98966.)

Notable changes in 3.10.12

tarfile

  • The extraction methods in tarfile, and shutil.unpack_archive(), have a new a filter argument that allows limiting tar features than may be surprising or dangerous, such as creating files outside the destination directory. See Extraction filters for details. In Python 3.12, use without the filter argument will show a DeprecationWarning. In Python 3.14, the default will switch to 'data'. (Contributed by Petr Viktorin in PEP 706.)