Novedades de Python 3.12

Editor:

Adam Turner

Este artículo explica las nuevas características de Python 3.12, en comparación con 3.11. Python 3.12 se lanzó el 2 de octubre de 2023. Para obtener detalles completos, consulte changelog.

Ver también

PEP 693 - Calendario de lanzamiento de Python 3.12

Resumen: aspectos destacados de la versión

Python 3.12 es la última versión estable del lenguaje de programación Python, con una combinación de cambios en el lenguaje y la biblioteca estándar. Los cambios en la biblioteca se centran en limpiar las API obsoletas, su usabilidad y su corrección. Es de destacar que el paquete distutils se ha eliminado de la biblioteca estándar. La compatibilidad con el sistema de archivos en os y pathlib ha experimentado una serie de mejoras y varios módulos tienen un mejor rendimiento.

Los cambios de idioma se centran en la usabilidad, ya que a f-strings se le han eliminado muchas limitaciones y las sugerencias «¿Quiso decir…» continúan mejorando. La nueva declaración type parameter syntax y type mejora la ergonomía para usar generic types y type aliases con controladores de tipo estático.

Este artículo no intenta proporcionar una especificación completa de todas las características nuevas, sino que brinda una descripción general conveniente. Para obtener detalles completos, debe consultar la documentación, como Library Reference y Language Reference. Si desea comprender la implementación completa y la justificación del diseño de un cambio, consulte el PEP para conocer una característica nueva en particular; pero tenga en cuenta que los PEP generalmente no se mantienen actualizados una vez que una característica se ha implementado por completo.


Nuevas características de sintaxis:

  • PEP 695, sintaxis de parámetro de tipo y sentencia type

Nuevas características gramaticales:

Mejoras del intérprete:

Mejoras en el modelo de datos de Python:

Mejoras significativas en la biblioteca estándar:

Mejoras de seguridad:

  • Reemplaza las implementaciones hashlib integradas de SHA1, SHA3, SHA2-384, SHA2-512 y MD5 con código verificado formalmente del proyecto HACL*. Estas implementaciones integradas permanecen como alternativas que solo se utilizan cuando OpenSSL no las proporciona.

Mejoras de la API C:

Mejoras en la implementación de CPython:

  • PEP 709, comprensión en línea

  • CPython support para el perfilador Linux perf

  • Implementar protección contra desbordamiento de pila en plataformas compatibles

Nuevas funciones de tipado:

Depreciaciones, eliminaciones o restricciones importantes:

  • PEP 623: elimina wstr de los objetos Unicode en la API C de Python, reduciendo el tamaño de cada objeto str en al menos 8 bytes.

  • PEP 632: elimina el paquete distutils. Consulte the migration guide para obtener consejos sobre cómo reemplazar las API que proporcionaba. El paquete Setuptools de terceros continúa proporcionando distutils, si aún lo necesita en Python 3.12 y versiones posteriores.

  • gh-95299: No preinstala setuptools en entornos virtuales creados con venv. Esto significa que distutils, setuptools, pkg_resources y easy_install ya no estarán disponibles de forma predeterminada; para acceder a ellos, ejecute pip install setuptools en el entorno virtual activated.

  • Se han eliminado los módulos asynchat, asyncore y imp, junto con varios unittest.TestCase method aliases.

Nuevas características

PEP 695: Sintaxis de parámetro de tipo

Las clases y funciones genéricas en PEP 484 se declararon utilizando una sintaxis detallada que dejaba el alcance de los parámetros de tipo poco claro y requería declaraciones explícitas de variación.

PEP 695 presenta una forma nueva, más compacta y explícita de crear generic classes y functions:

def max[T](args: Iterable[T]) -> T:
    ...

class list[T]:
    def __getitem__(self, index: int, /) -> T:
        ...

    def append(self, element: T) -> None:
        ...

Además, el PEP introduce una nueva forma de declarar type aliases utilizando la declaración type, que crea una instancia de TypeAliasType:

type Point = tuple[float, float]

Los alias de tipo también pueden ser generic:

type Point[T] = tuple[T, T]

La nueva sintaxis permite declarar los parámetros TypeVarTuple y ParamSpec, así como los parámetros TypeVar con límites o restricciones:

type IntFunc[**P] = Callable[P, int]  # ParamSpec
type LabeledTuple[*Ts] = tuple[str, *Ts]  # TypeVarTuple
type HashableSequence[T: Hashable] = Sequence[T]  # TypeVar with bound
type IntOrStrSequence[T: (int, str)] = Sequence[T]  # TypeVar with constraints

El valor de los alias de tipo y los límites y restricciones de las variables de tipo creadas mediante esta sintaxis se evalúan solo según demanda (consulte lazy evaluation). Esto significa que los alias de tipo pueden hacer referencia a otros tipos definidos más adelante en el archivo.

Los parámetros de tipo declarados a través de una lista de parámetros de tipo son visibles dentro del alcance de la declaración y de cualquier alcance anidado, pero no en el alcance externo. Por ejemplo, se pueden utilizar en las anotaciones de tipo de los métodos de una clase genérica o en el cuerpo de la clase. Sin embargo, no se pueden utilizar en el alcance del módulo una vez definida la clase. Consulte Type parameter lists para obtener una descripción detallada de la semántica de tiempo de ejecución de los parámetros de tipo.

Para respaldar esta semántica de alcance, se introduce un nuevo tipo de alcance, el annotation scope. Los ámbitos de anotación se comportan en su mayor parte como ámbitos de función, pero interactúan de manera diferente con los ámbitos de clase adjuntos. En Python 3.13, annotations también se evaluará en ámbitos de anotación.

Consulte PEP 695 para obtener más detalles.

(PEP escrito por Eric Traut. Implementación por Jelle Zijlstra, Eric Traut y otros en gh-103764.)

PEP 701: Formalización sintáctica de cadenas f

PEP 701 elimina algunas restricciones sobre el uso de f-strings. Los componentes de expresión dentro de cadenas f ahora pueden ser cualquier expresión Python válida, incluidas cadenas que reutilizan la misma comilla que la cadena f que las contiene, expresiones de varias líneas, comentarios, barras invertidas y secuencias de escape Unicode. Cubramos estos en detalle:

  • Reutilización de comillas: en Python 3.11, reutilizar las mismas comillas que la cadena f adjunta genera un SyntaxError, lo que obliga al usuario a usar otras comillas disponibles (como usar comillas dobles o triples si la cadena f usa comillas simples). En Python 3.12, ahora puedes hacer cosas como esta:

    >>> songs = ['Take me back to Eden', 'Alkaline', 'Ascensionism']
    >>> f"This is the playlist: {", ".join(songs)}"
    'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'
    

    Tenga en cuenta que antes de este cambio no había un límite explícito en cómo se pueden anidar las cadenas f, pero el hecho de que las comillas de cadena no se pueden reutilizar dentro del componente de expresión de las cadenas f hacía imposible anidar cadenas f arbitrariamente. De hecho, esta es la cadena f más anidada que podría escribirse:

    >>> f"""{f'''{f'{f"{1+1}"}'}'''}"""
    '2'
    

    Como ahora las cadenas f pueden contener cualquier expresión Python válida dentro de los componentes de expresión, ahora es posible anidar cadenas f de forma arbitraria:

    >>> f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}"
    '2'
    
  • Expresiones y comentarios de varias líneas: en Python 3.11, las expresiones de cadena f deben definirse en una sola línea, incluso si la expresión dentro de la cadena f normalmente podría abarcar varias líneas (como listas literales que se definen en varias líneas), lo que las hace más difícil de leer. En Python 3.12 ahora puedes definir cadenas f que abarquen varias líneas y agregar comentarios en línea:

    >>> f"This is the playlist: {", ".join([
    ...     'Take me back to Eden',  # My, my, those eyes like fire
    ...     'Alkaline',              # Not acid nor alkaline
    ...     'Ascensionism'           # Take to the broken skies at last
    ... ])}"
    'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'
    
  • Barras invertidas y caracteres Unicode: antes de Python 3.12, las expresiones de cadena f no podían contener ningún carácter \. Esto también afectó a Unicode escape sequences (como \N{snowman}), ya que contienen la parte \N que anteriormente no podía ser parte de los componentes de expresión de f-strings. Ahora puedes definir expresiones como esta:

    >>> print(f"This is the playlist: {"\n".join(songs)}")
    This is the playlist: Take me back to Eden
    Alkaline
    Ascensionism
    >>> print(f"This is the playlist: {"\N{BLACK HEART SUIT}".join(songs)}")
    This is the playlist: Take me back to Eden♥Alkaline♥Ascensionism
    

Consulte PEP 701 para obtener más detalles.

As a positive side-effect of how this feature has been implemented (by parsing f-strings with the PEG parser), now error messages for f-strings are more precise and include the exact location of the error. For example, in Python 3.11, the following f-string raises a SyntaxError:

>>> my_string = f"{x z y}" + f"{1 + 1}"
  File "<stdin>", line 1
    (x z y)
     ^^^
SyntaxError: f-string: invalid syntax. Perhaps you forgot a comma?

pero el mensaje de error no incluye la ubicación exacta del error dentro de la línea y también tiene la expresión artificialmente entre paréntesis. En Python 3.12, a medida que las cadenas f se analizan con el analizador PEG, los mensajes de error pueden ser más precisos y mostrar la línea completa:

>>> my_string = f"{x z y}" + f"{1 + 1}"
  File "<stdin>", line 1
    my_string = f"{x z y}" + f"{1 + 1}"
                   ^^^
SyntaxError: invalid syntax. Perhaps you forgot a comma?

(Aportado por Pablo Galindo, Batuhan Taskaya, Lysandros Nikolaou, Cristián Maureira-Fredes y Marta Gómez en gh-102856. PEP escrito por Pablo Galindo, Batuhan Taskaya, Lysandros Nikolaou y Marta Gómez).

PEP 684: un GIL por intérprete

PEP 684 introduce un GIL por intérprete, de modo que ahora se pueden crear subintérpretes con un GIL único por intérprete. Esto permite que los programas Python aprovechen al máximo múltiples núcleos de CPU. Actualmente, esto solo está disponible a través de C-API, aunque una API de Python es anticipada para 3.13.

Use the new Py_NewInterpreterFromConfig() function to create an interpreter with its own GIL:

PyInterpreterConfig config = {
    .check_multi_interp_extensions = 1,
    .gil = PyInterpreterConfig_OWN_GIL,
};
PyThreadState *tstate = NULL;
PyStatus status = Py_NewInterpreterFromConfig(&tstate, &config);
if (PyStatus_Exception(status)) {
    return -1;
}
/* The new interpreter is now active in the current thread. */

Para obtener más ejemplos de cómo utilizar C-API para subintérpretes con un GIL por intérprete, consulte Modules/_xxsubinterpretersmodule.c.

(Aportado por Eric Snow en gh-104210, etc.)

PEP 669: Monitoreo de bajo impacto para CPython

PEP 669 define un nuevo API para perfiladores, depuradores y otras herramientas para monitorear eventos en CPython. Cubre una amplia gama de eventos, incluidas llamadas, devoluciones, líneas, excepciones, saltos y más. Esto significa que solo paga por lo que usa, brindando soporte para depuradores generales y herramientas de cobertura casi nulos. Consulte sys.monitoring para obtener más detalles.

(Aportado por Mark Shannon en gh-103082.)

PEP 688: Hacer accesible el protocolo de búfer en Python

PEP 688 presenta una forma de utilizar buffer protocol desde el código Python. Las clases que implementan el método __buffer__() ahora se pueden utilizar como tipos de búfer.

El nuevo collections.abc.Buffer ABC proporciona una forma estándar de representar objetos de búfer, por ejemplo en anotaciones de tipo. La nueva enumeración inspect.BufferFlags representa los indicadores que se pueden usar para personalizar la creación del búfer. (Aportado por Jelle Zijlstra en gh-102500.)

PEP 709: Integración de la comprensión

Las comprensiones de diccionario, lista y conjunto ahora están integradas, en lugar de crear un nuevo objeto de función de un solo uso para cada ejecución de la comprensión. Esto acelera la ejecución de una comprensión hasta dos veces. Consulte PEP 709 para obtener más detalles.

Las variables de iteración de comprensión permanecen aisladas y no sobrescriben una variable del mismo nombre en el alcance externo, ni son visibles después de la comprensión. La incorporación da como resultado algunos cambios de comportamiento visibles:

  • Ya no hay un marco separado para la comprensión en los rastreos, y el rastreo/elaboración de perfiles ya no muestra la comprensión como una llamada a función.

  • El módulo symtable ya no producirá tablas de símbolos secundarios para cada comprensión; en cambio, los locales de comprensión se incluirán en la tabla de símbolos de la función principal.

  • Llamar a locals() dentro de una comprensión ahora incluye variables externas a la comprensión y ya no incluye la variable sintética .0 para el «argumento» de comprensión.

  • Una comprensión que itera directamente sobre locals() (por ejemplo, [k for k in locals()]) puede ver «RuntimeError: el diccionario cambió de tamaño durante la iteración» cuando se ejecuta bajo seguimiento (por ejemplo, medición de cobertura de código). Este es el mismo comportamiento que ya se ha visto, por ejemplo, en for k in locals():. Para evitar el error, primero cree una lista de claves para iterar: keys = list(locals()); [k for k in keys].

(Aportado por Carl Meyer y Vladimir Matveev en PEP 709.)

Mensajes de error mejorados

  • Ahora se sugieren potencialmente módulos de la biblioteca estándar como parte de los mensajes de error que muestra el intérprete cuando un NameError se eleva al nivel superior. (Aportado por Pablo Galindo en gh-98254.)

    >>> sys.version_info
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'sys' is not defined. Did you forget to import 'sys'?
    
  • Mejora la sugerencia de error para excepciones NameError para instancias. Ahora, si se genera un NameError en un método y la instancia tiene un atributo que es exactamente igual al nombre en la excepción, la sugerencia incluirá self.<NAME> en lugar de la coincidencia más cercana en el alcance del método. (Aportado por Pablo Galindo en gh-99139.)

    >>> class A:
    ...    def __init__(self):
    ...        self.blech = 1
    ...
    ...    def foo(self):
    ...        somethin = blech
    ...
    >>> A().foo()
    Traceback (most recent call last):
      File "<stdin>", line 1
        somethin = blech
                   ^^^^^
    NameError: name 'blech' is not defined. Did you mean: 'self.blech'?
    
  • Mejora el mensaje de error SyntaxError cuando el usuario escribe import x from y en lugar de from y import x. (Aportado por Pablo Galindo en gh-98931.)

    >>> import a.y.z from b.y.z
    Traceback (most recent call last):
      File "<stdin>", line 1
        import a.y.z from b.y.z
        ^^^^^^^^^^^^^^^^^^^^^^^
    SyntaxError: Did you mean to use 'from ... import ...' instead?
    
  • Las excepciones ImportError generadas por sentencias from <module> import <name> fallidas ahora incluyen sugerencias para el valor de <name> según los nombres disponibles en <module>. (Aportado por Pablo Galindo en gh-91058.)

    >>> from collections import chainmap
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ImportError: cannot import name 'chainmap' from 'collections'. Did you mean: 'ChainMap'?
    

Otros cambios del lenguaje

  • El analizador ahora genera SyntaxError al analizar el código fuente que contiene bytes nulos. (Aportado por Pablo Galindo en gh-96670.)

  • Un par de caracteres de barra invertida que no es una secuencia de escape válida ahora genera un SyntaxWarning, en lugar de DeprecationWarning. Por ejemplo, re.compile("\d+\.\d+") ahora emite un SyntaxWarning ("\d" es una secuencia de escape no válida; utilice cadenas sin formato para la expresión regular: re.compile(r"\d+\.\d+")). En una versión futura de Python, eventualmente se generará SyntaxError, en lugar de SyntaxWarning. (Aportado por Victor Stinner en gh-98401.)

  • Los escapes octales con un valor mayor que 0o377 (por ejemplo, "\477"), obsoletos en Python 3.11, ahora producen un SyntaxWarning, en lugar de DeprecationWarning. En una futura versión de Python, eventualmente serán un SyntaxError. (Aportado por Victor Stinner en gh-98401.)

  • Las variables utilizadas en la parte de destino de las comprensiones que no están almacenadas ahora se pueden usar en expresiones de asignación (:=). Por ejemplo, en [(b := 1) for a, b.prop in some_iter], ahora se permite la asignación a b. Tenga en cuenta que la asignación de variables almacenadas en la parte de destino de las comprensiones (como a) todavía no está permitida, según PEP 572. (Aportado por Nikita Sobolev en gh-100581.)

  • Las excepciones generadas en el método __set_name__ de una clase o tipo ya no están incluidas en un RuntimeError. La información de contexto se agrega a la excepción como una nota PEP 678. (Aportado por Irit Katriel en gh-77757.)

  • Cuando una construcción try-except* maneja todo el ExceptionGroup y genera otra excepción, esa excepción ya no está incluida en un ExceptionGroup. También cambió en la versión 3.11.4. (Aportado por Irit Katriel en gh-103590.)

  • El recolector de basura ahora se ejecuta solo en el mecanismo de interrupción de evaluación del ciclo de evaluación del código de bytes de Python en lugar de en las asignaciones de objetos. El GC también se puede ejecutar cuando se llama a PyErr_CheckSignals(), por lo que las extensiones C que necesitan ejecutarse durante un período prolongado sin ejecutar ningún código Python también tienen la posibilidad de ejecutar el GC periódicamente. (Aportado por Pablo Galindo en gh-97922.)

  • Todos los invocables integrados y de extensión que esperan parámetros booleanos ahora aceptan argumentos de cualquier tipo en lugar de solo bool y int. (Contribución de Serhiy Storchaka en gh-60203.)

  • memoryview ahora admite el tipo medio flotante (el código de formato «e»). (Contribución de Donghee Na y Antoine Pitrou en gh-90751.)

  • Los objetos slice ahora son hasheables, lo que permite usarlos como claves de dictado y elementos de configuración. (Contribución de Will Bradshaw, Furkan Onder y Raymond Hettinger en gh-101264.)

  • sum() ahora utiliza la suma de Neumaier para mejorar la precisión y la conmutatividad al sumar flotantes o enteros y flotantes mixtos. (Aportado por Raymond Hettinger en gh-100425.)

  • ast.parse() ahora genera SyntaxError en lugar de ValueError al analizar el código fuente que contiene bytes nulos. (Aportado por Pablo Galindo en gh-96670.)

  • Los métodos de extracción en tarfile y shutil.unpack_archive() tienen un nuevo argumento, filter, que permite limitar funciones tar que puedan resultar sorprendentes o peligrosas, como la creación de archivos fuera del directorio de destino. Consulte tarfile extraction filters para obtener más detalles. En Python 3.14, el valor predeterminado cambiará a 'data'. (Aportado por Petr Viktorin en PEP 706.)

  • Las instancias types.MappingProxyType ahora son hasheables si el mapeo subyacente es hasheable. (Contribución de Serhiy Storchaka en gh-87995.)

  • Agregado support for the perf profiler a través de la nueva variable de entorno PYTHONPERFSUPPORT y la opción de línea de comandos -X perf, así como las nuevas funciones sys.activate_stack_trampoline(), sys.deactivate_stack_trampoline() y sys.is_stack_trampoline_active(). (Diseño de Pablo Galindo. Contribución de Pablo Galindo y Christian Heimes con contribuciones de Gregory P. Smith [Google] y Mark Shannon en gh-96123.)

Nuevos módulos

  • Ninguno.

Módulos mejorados

array

asincio

calendar

csv

dis

  • Los códigos de operación de pseudoinstrucción (que son utilizados por el compilador pero que no aparecen en el código de bytes ejecutable) ahora están expuestos en el módulo dis. HAVE_ARGUMENT sigue siendo relevante para códigos de operación reales, pero no es útil para pseudoinstrucciones. Utilice la nueva colección dis.hasarg en su lugar. (Aportado por Irit Katriel en gh-94216.)

  • Agregado la colección dis.hasexc para indicar instrucciones que establecen un controlador de excepciones. (Aportado por Irit Katriel en gh-94216.)

fractions

importlib.resources

inspect

itertools

  • Agregado itertools.batched() para recopilar en tuplas de tamaño par donde el último lote puede ser más corto que el resto. (Aportado por Raymond Hettinger en gh-98363.)

math

  • Agregado math.sumprod() para calcular una suma de productos. (Aportado por Raymond Hettinger en gh-100485.)

  • Extend math.nextafter() to include a steps argument for moving up or down multiple steps at a time. (Contributed by Matthias Goergens, Mark Dickinson, and Raymond Hettinger in gh-94906.)

os

  • Agregado os.PIDFD_NONBLOCK para abrir un descriptor de archivo para un proceso con os.pidfd_open() en modo sin bloqueo. (Aportado por Kumar Aditya en gh-93312.)

  • os.DirEntry ahora incluye un método os.DirEntry.is_junction() para verificar si la entrada es un cruce. (Aportado por Charles Machalow en gh-99547.)

  • Agregado funciones os.listdrives(), os.listvolumes() y os.listmounts() en Windows para enumerar unidades, volúmenes y puntos de montaje. (Aportado por Steve Dower en gh-102519.)

  • os.stat() y os.lstat() ahora son más precisos en Windows. El campo st_birthtime ahora se completará con la hora de creación del archivo, y st_ctime está obsoleto pero aún contiene la hora de creación (pero en el futuro devolverá el último cambio de metadatos, para mantener la coherencia con otras plataformas). st_dev puede tener hasta 64 bits y st_ino hasta 128 bits dependiendo de su sistema de archivos, y st_rdev siempre está configurado en cero en lugar de valores incorrectos. Ambas funciones pueden ser significativamente más rápidas en las versiones más recientes de Windows. (Aportado por Steve Dower en gh-99726.)

os.path

pathlib

pbd

  • Agregado variables convenientes para mantener valores temporalmente para la sesión de depuración y proporcionar acceso rápido a valores como el marco actual o el valor de retorno. (Aportado por Tian Gao en gh-103693.)

random

shutil

  • shutil.make_archive() ahora pasa el argumento root_dir a archivadores personalizados que lo admiten. En este caso, ya no cambia temporalmente el directorio de trabajo actual del proceso a root_dir para realizar el archivado. (Aportado por Serhiy Storchaka en gh-74696.)

  • shutil.rmtree() now accepts a new argument onexc which is an error handler like onerror but which expects an exception instance rather than a (typ, val, tb) triplet. onerror is deprecated. (Contributed by Irit Katriel in gh-102828.)

  • shutil.which() ahora consulta la variable de entorno PATHEXT para encontrar coincidencias dentro de PATH en Windows incluso cuando el cmd dado incluye un componente de directorio. (Aportado por Charles Machalow en gh-103179.)

    shutil.which() llamará a NeedCurrentDirectoryForExePathW cuando solicite ejecutables en Windows para determinar si el directorio de trabajo actual debe anteponerse a la ruta de búsqueda. (Aportado por Charles Machalow en gh-103179.)

    shutil.which() devolverá una ruta que coincida con cmd con un componente de PATHEXT antes de una coincidencia directa en otra parte de la ruta de búsqueda en Windows. (Aportado por Charles Machalow en gh-103179.)

sqlite3

statistics

  • Se extendió statistics.correlation() para incluirlo como método ranked para calcular la correlación de Spearman de datos clasificados. (Aportado por Raymond Hettinger en gh-95861.)

sys

tempfile

  • La función tempfile.NamedTemporaryFile tiene un nuevo parámetro opcional delete_on_close (Aportado por Evgeny Zorin en gh-58451.)

  • tempfile.mkdtemp() ahora siempre devuelve una ruta absoluta, incluso si el argumento proporcionado al parámetro dir es una ruta relativa.

threading

tkinter

  • tkinter.Canvas.coords() ahora aplana sus argumentos. Ahora acepta no sólo coordenadas como argumentos separados (x1, y1, x2, y2, ...) y una secuencia de coordenadas ([x1, y1, x2, y2, ...]), sino también coordenadas agrupadas en pares ((x1, y1), (x2, y2), ... y [(x1, y1), (x2, y2), ...]), como los métodos create_*(). (Aportado por Serhiy Storchaka en gh-94473.)

tokenize

types

typing

  • Las comprobaciones de isinstance() con runtime-checkable protocols ahora usan inspect.getattr_static() en lugar de hasattr() para buscar si existen atributos. Esto significa que los descriptores y los métodos __getattr__() ya no se evalúan inesperadamente durante las comprobaciones de isinstance() con protocolos verificables en tiempo de ejecución. Sin embargo, también puede significar que algunos objetos que solían considerarse instancias de un protocolo verificable en tiempo de ejecución ya no se consideran instancias de ese protocolo en Python 3.12+, y viceversa. Es poco probable que la mayoría de los usuarios se vean afectados por este cambio. (Contribuido por Alex Waygood en gh-102433.)

  • Los miembros de un protocolo verificable en tiempo de ejecución ahora se consideran «congelados» en tiempo de ejecución tan pronto como se crea la clase. La aplicación de parches de atributos en un protocolo verificable en tiempo de ejecución seguirá funcionando, pero no tendrá ningún impacto en las comprobaciones isinstance() que comparan objetos con el protocolo. Por ejemplo:

    >>> from typing import Protocol, runtime_checkable
    >>> @runtime_checkable
    ... class HasX(Protocol):
    ...     x = 1
    ...
    >>> class Foo: ...
    ...
    >>> f = Foo()
    >>> isinstance(f, HasX)
    False
    >>> f.x = 1
    >>> isinstance(f, HasX)
    True
    >>> HasX.y = 2
    >>> isinstance(f, HasX)  # unchanged, even though HasX now also has a "y" attribute
    True
    

    Este cambio se realizó para acelerar las comprobaciones de isinstance() en protocolos verificables en tiempo de ejecución.

  • El perfil de rendimiento de las comprobaciones de isinstance() frente a runtime-checkable protocols ha cambiado significativamente. La mayoría de las comprobaciones de isinstance() en protocolos con solo unos pocos miembros deberían ser al menos 2 veces más rápidas que en 3.11, y algunas pueden ser 20 veces más rápidas o más. Sin embargo, las comprobaciones de isinstance() con protocolos con catorce o más miembros pueden ser más lentas que en Python 3.11. (Contribuido por Alex Waygood en gh-74690 y gh-103193.)

  • Todas las clases typing.TypedDict y typing.NamedTuple ahora tienen el atributo __orig_bases__. (Aportado por Adrián García Badaracco en gh-103699.)

  • Agregado el parámetro frozen_default a typing.dataclass_transform(). (Aportado por Erik De Bonte en gh-99957.)

unicodedata

  • La base de datos Unicode se ha actualizado a la versión 15.0.0. (Aportado por Benjamin Peterson en gh-96734).

unittest

Agregado una opción de línea de comando --durations, que muestra los N casos de prueba más lentos:

python3 -m unittest --durations=3 lib.tests.test_threading
.....
Slowest test durations
----------------------------------------------------------------------
1.210s     test_timeout (Lib.test.test_threading.BarrierTests)
1.003s     test_default_timeout (Lib.test.test_threading.BarrierTests)
0.518s     test_timeout (Lib.test.test_threading.EventTests)

(0.000 durations hidden.  Use -v to show these durations.)
----------------------------------------------------------------------
Ran 158 tests in 9.869s

OK (skipped=3)

(Aportado por Giampaolo Rodola en gh-48330)

uuid

Optimizaciones

  • Elimine los miembros wstr y wstr_length de los objetos Unicode. Reduce el tamaño del objeto en 8 o 16 bytes en una plataforma de 64 bits. (PEP 623) (Aportado por Inada Naoki en gh-92536.)

  • Agregado soporte experimental para usar el optimizador binario BOLT en el proceso de compilación, lo que mejora el rendimiento entre un 1% y un 5%. (Contribuido por Kevin Modzelewski en gh-90536 y sintonizado por Donghee Na en gh-101525)

  • Acelere la sustitución de expresiones regulares (funciones re.sub() y re.subn() y los métodos re.Pattern correspondientes) para cadenas de reemplazo que contienen referencias de grupo entre 2 y 3 veces. (Aportado por Serhiy Storchaka en gh-91524.)

  • Acelere la creación de asyncio.Task aplazando el costoso formato de cadenas. (Aportado por Itamar Oren en gh-103793.)

  • Las funciones tokenize.tokenize() y tokenize.generate_tokens() son hasta un 64 % más rápidas como efecto secundario de los cambios necesarios para cubrir PEP 701 en el módulo tokenize. (Aportado por Marta Gómez Macías y Pablo Galindo en gh-102856.)

  • Acelere las llamadas al método super() y las cargas de atributos mediante la nueva instrucción LOAD_SUPER_ATTR. (Contribución de Carl Meyer y Vladimir Matveev en gh-103497.)

Cambios en el código de bytes de CPython

Demostraciones y herramientas

  • Elimine el directorio Tools/demo/ que contenía scripts de demostración antiguos. Se puede encontrar una copia en el old-demos project. (Aportado por Victor Stinner en gh-97681.)

  • Elimine los scripts de ejemplo obsoletos del directorio Tools/scripts/. Se puede encontrar una copia en el old-demos project. (Aportado por Victor Stinner en gh-97669.)

Obsoleto

Eliminación pendiente en Python 3.13

Los siguientes módulos y API quedaron obsoletos en versiones anteriores de Python y se eliminarán en Python 3.13.

Módulos (ver PEP 594):

Otros módulos:

APIs:

Eliminación pendiente en Python 3.14

Las siguientes API han quedado obsoletas y se eliminarán en Python 3.14.

  • argparse: Los parámetros type, choices y metavar de argparse.BooleanOptionalAction

  • ast:

    • ast.Num

    • ast.Str

    • ast.Bytes

    • ast.NameConstant

    • ast.Ellipsis

  • asyncio:

    • asyncio.MultiLoopChildWatcher

    • asyncio.FastChildWatcher

    • asyncio.AbstractChildWatcher

    • asyncio.SafeChildWatcher

    • asyncio.set_child_watcher()

    • asyncio.get_child_watcher(),

    • asyncio.AbstractEventLoopPolicy.set_child_watcher()

    • asyncio.AbstractEventLoopPolicy.get_child_watcher()

  • collections.abc: collections.abc.ByteString.

  • email: el parámetro isdst en email.utils.localtime().

  • importlib.abc:

    • importlib.abc.ResourceReader

    • importlib.abc.Traversable

    • importlib.abc.TraversableResources

  • itertools: soporte para operaciones de copia, copia profunda y pickle.

  • pkgutil:

    • pkgutil.find_loader()

    • pkgutil.get_loader().

  • pty:

    • pty.master_open()

    • pty.slave_open()

  • shutil: El argumento onerror de shutil.rmtree()

  • typing: typing.ByteString

  • xml.etree.ElementTree: Probando el valor de verdad de un xml.etree.ElementTree.Element.

  • Los atributos __package__ y __cached__ en los objetos del módulo.

  • The co_lnotab attribute of code objects.

Eliminación pendiente en Python 3.15

The following APIs have been deprecated and will be removed in Python 3.15.

APIs:

Eliminación pendiente en versiones futuras

Las siguientes API quedaron obsoletas en versiones anteriores de Python y se eliminarán, aunque actualmente no hay una fecha programada para su eliminación.

  • Código de formato 'u' de array (gh-57281)

  • typing.Text (gh-92332)

  • Actualmente, Python acepta literales numéricos seguidos inmediatamente de palabras clave, por ejemplo 0in x, 1or x, 0if 1else 2. Permite expresiones confusas y ambiguas como [0x1for x in y] (que puede interpretarse como [0x1 for x in y] o [0x1f or x in y]). Se genera una advertencia de sintaxis si el literal numérico va seguido inmediatamente de una de las palabras clave and, else, for, if, in, is y or. En una versión futura se cambiará a un error de sintaxis. (gh-87999)

Eliminado

asynchat y asyncore

  • Estos dos módulos se eliminaron según lo programado en PEP 594 y quedaron obsoletos en Python 3.6. Utilice asyncio en su lugar. (Aportado por Nikita Sobolev en gh-96580.)

configparser

distutils

  • Elimine el paquete distutils. Quedó obsoleto en Python 3.10 por PEP 632 «Módulo distutils obsoleto». Para proyectos que todavía usan distutils y no se pueden actualizar a otra cosa, se puede instalar el proyecto setuptools: todavía proporciona distutils. (Aportado por Victor Stinner en gh-92584.)

ensurepip

  • Retire la rueda de herramientas de configuración incluida en ensurepip y deje de instalar herramientas de configuración en entornos creados por venv.

    pip (>= 22.1) no requiere la instalación de herramientas de configuración en el entorno. Los paquetes basados ​​en setuptools (y distutils) aún se pueden usar con pip install, ya que pip proporcionará setuptools en el entorno de compilación que utiliza para crear un paquete.

    easy_install, pkg_resources, setuptools y distutils ya no se proporcionan de forma predeterminada en entornos creados con venv o arrancados con ensurepip, ya que forman parte del paquete setuptools. Para proyectos que dependen de estos en tiempo de ejecución, el proyecto setuptools debe declararse como una dependencia e instalarse por separado (generalmente, usando pip).

    (Aportado por Pradyun Gedam en gh-95299.)

enum

  • Elimine EnumMeta.__getattr__ de enum, que ya no es necesario para acceder al atributo de enumeración. (Aportado por Ethan Furman en gh-95083.)

ftplib

  • Elimine el atributo de clase FTP_TLS.ssl_version de ftplib: utilice el parámetro context en su lugar. (Aportado por Victor Stinner en gh-94172.)

gzip

  • Elimine el atributo filename del gzip.GzipFile de gzip, en desuso desde Python 2.6; utilice el atributo name en su lugar. En modo de escritura, el atributo filename agregaba la extensión de archivo '.gz' si no estaba presente. (Aportado por Victor Stinner en gh-94196.)

hashlib

  • Elimine la implementación pura de Python de hashlib.pbkdf2_hmac() de hashlib, obsoleta en Python 3.10. Python 3.10 y versiones posteriores requieren OpenSSL 1.1.1 (PEP 644): esta versión de OpenSSL proporciona una implementación C de pbkdf2_hmac() que es más rápida. (Aportado por Victor Stinner en gh-94199.)

importlib

  • Muchas limpiezas anteriormente obsoletas en importlib ahora se han completado:

    • Se han eliminado las referencias y la compatibilidad con module_repr(). (Aportado por Barry Varsovia en gh-97850.)

    • Se han eliminado importlib.util.set_package, importlib.util.set_loader y importlib.util.module_for_loader. (Contribución de Brett Cannon y Nikita Sobolev en gh-65961 y gh-97850.)

    • Se eliminó la compatibilidad con las API find_loader() y find_module(). (Aportado por Barry Varsovia en gh-98040.)

    • Se han eliminado importlib.abc.Finder, pkgutil.ImpImporter y pkgutil.ImpLoader. (Aportado por Barry Varsovia en gh-98040.)

imp

  • Se ha eliminado el módulo imp. (Aportado por Barry Varsovia en gh-98040.)

    Para migrar consulte la siguiente tabla de correspondencias:

    imp

    importlib

    imp.NullImporter

    Inserta None en sys.path_importer_cache

    imp.cache_from_source()

    importlib.util.cache_from_source()

    imp.find_module()

    importlib.util.find_spec()

    imp.get_magic()

    importlib.util.MAGIC_NUMBER

    imp.get_suffixes()

    importlib.machinery.SOURCE_SUFFIXES, importlib.machinery.EXTENSION_SUFFIXES y importlib.machinery.BYTECODE_SUFFIXES

    imp.get_tag()

    sys.implementation.cache_tag

    imp.load_module()

    importlib.import_module()

    imp.new_module(name)

    types.ModuleType(name)

    imp.reload()

    importlib.reload()

    imp.source_from_cache()

    importlib.util.source_from_cache()

    imp.load_source()

    Ver abajo

    Reemplace imp.load_source() con:

    import importlib.util
    import importlib.machinery
    
    def load_source(modname, filename):
        loader = importlib.machinery.SourceFileLoader(modname, filename)
        spec = importlib.util.spec_from_file_location(modname, filename, loader=loader)
        module = importlib.util.module_from_spec(spec)
        # The module is always executed and not cached in sys.modules.
        # Uncomment the following line to cache the module.
        # sys.modules[module.__name__] = module
        loader.exec_module(module)
        return module
    
  • Elimine las funciones y atributos de imp sin reemplazos:

    • Funciones no documentadas:

      • imp.init_builtin()

      • imp.load_compiled()

      • imp.load_dynamic()

      • imp.load_package()

    • imp.lock_held(), imp.acquire_lock(), imp.release_lock(): el esquema de bloqueo ha cambiado en Python 3.3 a bloqueos por módulo.

    • Constantes imp.find_module(): SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION, PY_RESOURCE, PKG_DIRECTORY, C_BUILTIN, PY_FROZEN, PY_CODERESOURCE, IMP_HOOK.

io

  • Elimine io.OpenWrapper y _pyio.OpenWrapper de io, obsoletos en Python 3.10: simplemente use open() en su lugar. La función open() (io.open()) es una función incorporada. Desde Python 3.10, _pyio.open() también es un método estático. (Aportado por Victor Stinner en gh-94169.)

locale

smtpd

  • The smtpd module has been removed according to the schedule in PEP 594, having been deprecated in Python 3.4.7 and 3.5.4. Use the aiosmtpd PyPI module or any other asyncio-based server instead. (Contributed by Oleg Iarygin in gh-93243.)

sqlite3

  • Las siguientes características sqlite3 no documentadas, obsoletas en Python 3.10, ahora se eliminan:

    • sqlite3.enable_shared_cache()

    • sqlite3.OptimizedUnicode

    Si se debe utilizar una caché compartida, abra la base de datos en modo URI utilizando el parámetro de consulta cache=shared.

    La fábrica de textos sqlite3.OptimizedUnicode ha sido un alias para str desde Python 3.3. El código que previamente configuró la fábrica de texto en OptimizedUnicode puede usar str explícitamente o confiar en el valor predeterminado que también es str.

    (Aportado por Erlend E. Aasland en gh-92548.)

ssl

  • Elimine la función ssl.RAND_pseudo_bytes() de ssl, obsoleta en Python 3.6: use os.urandom() o ssl.RAND_bytes() en su lugar. (Aportado por Victor Stinner en gh-94199.)

  • Elimine la función ssl.match_hostname(). Quedó obsoleto en Python 3.7. OpenSSL realiza coincidencias de nombres de host desde Python 3.7, Python ya no usa la función ssl.match_hostname(). (Aportado por Victor Stinner en gh-94199.)

  • Remove the ssl.wrap_socket() function, deprecated in Python 3.7: instead, create a ssl.SSLContext object and call its ssl.SSLContext.wrap_socket method. Any package that still uses ssl.wrap_socket() is broken and insecure. The function neither sends a SNI TLS extension nor validates the server hostname. Code is subject to CWE-295 (Improper Certificate Validation). (Contributed by Victor Stinner in gh-94199.)

unittest

webbrowser

  • Elimina la compatibilidad con navegadores obsoletos de webbrowser. Los navegadores eliminados incluyen: Grail, Mosaic, Netscape, Galeon, Skipstone, Iceape, Firebird y Firefox versiones 35 e inferiores (gh-102871).

xml.etree.ElementTree

  • Elimine el método ElementTree.Element.copy() de la implementación pura de Python, obsoleto en Python 3.10, use la función copy.copy() en su lugar. La implementación C de xml.etree.ElementTree no tiene ningún método copy(), solo un método __copy__(). (Aportado por Victor Stinner en gh-94383.)

zipimport

  • Elimine los métodos find_loader() y find_module() de zipimport, obsoletos en Python 3.10: use el método find_spec() en su lugar. Consulte PEP 451 para conocer el fundamento. (Aportado por Victor Stinner en gh-94379.)

Otros

  • Elimine la regla suspicious de la documentación Makefile y Doc/tools/rstlint.py, ambas a favor de sphinx-lint. (Contribución de Julien Palard en gh-98179.)

  • Elimine los parámetros keyfile y certfile de los módulos ftplib, imaplib, poplib y smtplib, y los parámetros key_file, cert_file y check_hostname del módulo http.client, todos obsoletos desde Python 3.6. Utilice el parámetro context (ssl_context en imaplib) en su lugar. (Aportado por Victor Stinner en gh-94172.)

  • Elimine los trucos de compatibilidad Jython de varios módulos y pruebas stdlib. (Aportado por Nikita Sobolev en gh-99482.)

  • Elimine el indicador _use_broken_old_ctypes_structure_semantics_ del módulo ctypes. (Aportado por Nikita Sobolev en gh-99285.)

Portar a Python 3.12

Esta sección enumera los cambios descritos anteriormente y otras correcciones de errores que pueden requerir cambios en su código.

Cambios en la API de Python

  • Ahora se aplican reglas más estrictas para las referencias numéricas de grupos y los nombres de grupos en expresiones regulares. Ahora sólo se acepta como referencia numérica la secuencia de dígitos ASCII. El nombre del grupo en patrones de bytes y cadenas de reemplazo ahora solo puede contener letras y dígitos ASCII y guiones bajos. (Contribución de Serhiy Storchaka en gh-91760.)

  • Elimine la funcionalidad randrange() en desuso desde Python 3.10. Anteriormente, randrange(10.0) se convertía sin pérdidas a randrange(10). Ahora, genera un TypeError. Además, la excepción planteada para valores no enteros como randrange(10.5) o randrange('10') se cambió de ValueError a TypeError. Esto también evita errores en los que randrange(1e25) seleccionaría silenciosamente de un rango mayor que randrange(10**25). (Originalmente sugerido por Serhiy Storchaka gh-86388.)

  • argparse.ArgumentParser cambió la codificación y el controlador de errores para leer argumentos de un archivo (por ejemplo, la opción fromfile_prefix_chars) de la codificación de texto predeterminada (por ejemplo, locale.getpreferredencoding(False)) a filesystem encoding and error handler. Los archivos de argumentos deben codificarse en UTF-8 en lugar de en la página de códigos ANSI en Windows.

  • Remove the asyncore-based smtpd module deprecated in Python 3.4.7 and 3.5.4. A recommended replacement is the asyncio-based aiosmtpd PyPI module.

  • shlex.split(): Pasar None por el argumento s ahora genera una excepción, en lugar de leer sys.stdin. La característica quedó obsoleta en Python 3.9. (Aportado por Victor Stinner en gh-94352.)

  • El módulo os ya no acepta rutas tipo bytes, como los tipos bytearray y memoryview: solo se acepta el tipo exacto bytes para cadenas de bytes. (Aportado por Victor Stinner en gh-98393.)

  • syslog.openlog() y syslog.closelog() ahora fallan si se usan en subintérpretes. syslog.syslog() aún se puede usar en subintérpretes, pero ahora solo si syslog.openlog() ya ha sido llamado en el intérprete principal. Estas nuevas restricciones no se aplican al intérprete principal, por lo que sólo un conjunto muy pequeño de usuarios podría verse afectado. Este cambio ayuda con el aislamiento del intérprete. Además, syslog es un contenedor de recursos globales de procesos, que se administran mejor desde el intérprete principal. (Aportado por Donghee Na en gh-99127.)

  • Se elimina el comportamiento de bloqueo no documentado de cached_property(), porque bloqueaba todas las instancias de la clase, lo que generaba una alta contención de bloqueo. Esto significa que una función de obtención de propiedades almacenadas en caché ahora podría ejecutarse más de una vez para una sola instancia, si dos subprocesos se ejecutan. Para la mayoría de las propiedades almacenadas en caché simples (por ejemplo, aquellas que son idempotentes y simplemente calculan un valor en función de otros atributos de la instancia), esto estará bien. Si se necesita sincronización, implemente el bloqueo dentro de la función de obtención de propiedades en caché o alrededor de puntos de acceso de subprocesos múltiples.

  • sys._current_exceptions() ahora devuelve una asignación de thread-id a una instancia de excepción, en lugar de a una tupla (typ, exc, tb). (Aportado por Irit Katriel en gh-103176.)

  • Al extraer archivos tar usando tarfile o shutil.unpack_archive(), pase el argumento filter para limitar las funciones que pueden resultar sorprendentes o peligrosas. Consulte Extraction filters para obtener más detalles.

  • La salida de las funciones tokenize.tokenize() y tokenize.generate_tokens() ahora cambia debido a los cambios introducidos en PEP 701. Esto significa que los tokens STRING ya no se emiten para cadenas f y los tokens descritos en PEP 701 ahora se producen en su lugar: FSTRING_START, FSTRING_MIDDLE y FSTRING_END ahora se emiten para partes de «cadena» de cadena f además de los tokens apropiados para la tokenización. en los componentes de la expresión. Por ejemplo, para la cadena f f"start {1+1} end", la versión anterior del tokenizador emitió:

    1,0-1,18:           STRING         'f"start {1+1} end"'
    

    mientras que la nueva versión emite:

    1,0-1,2:            FSTRING_START  'f"'
    1,2-1,8:            FSTRING_MIDDLE 'start '
    1,8-1,9:            OP             '{'
    1,9-1,10:           NUMBER         '1'
    1,10-1,11:          OP             '+'
    1,11-1,12:          NUMBER         '1'
    1,12-1,13:          OP             '}'
    1,13-1,17:          FSTRING_MIDDLE ' end'
    1,17-1,18:          FSTRING_END    '"'
    

    Además, puede haber algunos cambios de comportamiento menores como consecuencia de los cambios necesarios para admitir PEP 701. Algunos de estos cambios incluyen:

    • El atributo type de los tokens emitidos al tokenizar algunos caracteres de Python no válidos, como !, ha cambiado de ERRORTOKEN a OP.

    • Las cadenas incompletas de una sola línea ahora también generan tokenize.TokenError como lo hacen las cadenas incompletas de varias líneas.

    • Algún código Python incompleto o no válido ahora genera tokenize.TokenError en lugar de devolver tokens ERRORTOKEN arbitrarios al tokenizarlo.

    • Ya no se admite la combinación de tabulaciones y espacios como sangría en el mismo archivo y generará un TabError.

  • The threading module now expects the _thread module to have an _is_main_interpreter attribute. It is a function with no arguments that returns True if the current interpreter is the main interpreter.

    Any library or application that provides a custom _thread module should provide _is_main_interpreter(). (See gh-112826.)

Cambios de compilación

  • Python ya no usa setup.py para crear módulos de extensión C compartidos. Los parámetros de compilación, como encabezados y bibliotecas, se detectan en el script configure. Las extensiones están construidas por Makefile. La mayoría de las extensiones usan pkg-config y recurren a la detección manual. (Aportado por Christian Heimes en gh-93939.)

  • Ahora se requiere va_start() con dos parámetros, como va_start(args, format),, para compilar Python. va_start() ya no se llama con un solo parámetro. (Aportado por Kumar Aditya en gh-93207.)

  • CPython ahora usa la opción ThinLTO como política predeterminada de optimización del tiempo de enlace si el compilador Clang acepta la marca. (Aportado por Donghee Na en gh-89536.)

  • Agregado la variable COMPILEALL_OPTS en Makefile para anular las opciones de compileall (predeterminada: -j0) en make install. También fusionó los 3 comandos compileall en un solo comando para crear archivos .pyc para todos los niveles de optimización (0, 1, 2) a la vez. (Aportado por Victor Stinner en gh-99289.)

  • Agregado tripletes de plataforma para LoongArch de 64 bits:

    • loongarch64-linux-gnusf

    • loongarch64-linux-gnuf32

    • loongarch64-linux-gnu

    (Aportado por Zhang Na en gh-90656.)

  • PYTHON_FOR_REGEN ahora requiere Python 3.10 o posterior.

  • Ahora se requieren Autoconf 2.71 y aclocal 1.16.4 para regenerar !configure. (Aportado por Christian Heimes en gh-89886.)

  • Las compilaciones de Windows y los instaladores de macOS de python.org ahora usan OpenSSL 3.0.

Cambios en la API de C

Nuevas características

  • PEP 683: presente Immortal Objects, que permite que los objetos omitan los recuentos de referencias y los cambios relacionados en C-API:

    • _Py_IMMORTAL_REFCNT: el recuento de referencias que define un objeto

      como inmortal.

    • _Py_IsImmortal Comprueba si un objeto tiene el recuento de referencia inmortal.

    • PyObject_HEAD_INIT Esto ahora inicializará el recuento de referencias

      _Py_IMMORTAL_REFCNT cuando se utiliza con Py_BUILD_CORE.

    • SSTATE_INTERNED_IMMORTAL Un identificador para objetos Unicode internos

      que son inmortales.

    • SSTATE_INTERNED_IMMORTAL_STATIC Un identificador para Unicode interno

      Objetos inmortales y estáticos.

    • sys.getunicodeinternedsize Esto devuelve el número total de Unicode

      objetos que han sido internados. Esto ahora es necesario para que refleak.py rastree correctamente los recuentos de referencia y los bloques asignados.

    (Contribuido por Eddie Elizondo en gh-84436.)

  • PEP 684: agregue la nueva función Py_NewInterpreterFromConfig() y PyInterpreterConfig, que pueden usarse para crear subintérpretes con sus propios GIL. (Consulte PEP 684: un GIL por intérprete para obtener más información). (Contribución de Eric Snow en gh-104110.)

  • En la versión limitada de C API 3.12, las funciones Py_INCREF() y Py_DECREF() ahora se implementan como llamadas de función opacas para ocultar los detalles de implementación. (Aportado por Victor Stinner en gh-105387.)

Portar a Python 3.12

  • Se han eliminado las API Unicode heredadas basadas en la representación Py_UNICODE*. Migre a API basadas en UTF-8 o wchar_t*.

  • Las funciones de análisis de argumentos como PyArg_ParseTuple() ya no admiten el formato basado en Py_UNICODE* (por ejemplo, u, Z). Migre a otros formatos para Unicode como s, z, es y U.

  • tp_weaklist para todos los tipos integrados estáticos siempre es NULL. Este es un campo solo interno en PyTypeObject, pero señalamos el cambio en caso de que alguien acceda al campo directamente de todos modos. Para evitar roturas, considere utilizar la C-API pública existente o, si es necesario, la macro _PyObject_GET_WEAKREFS_LISTPTR() (solo interna).

  • Es posible que este PyTypeObject.tp_subclasses solo interno ya no sea un puntero de objeto válido. Su tipo se cambió a void* para reflejar esto. Mencionamos esto en caso de que alguien acceda directamente al campo interno.

    Para obtener una lista de subclases, llame al método Python __subclasses__() (usando PyObject_CallMethod(), por ejemplo).

  • Agregado soporte para más opciones de formato (alineación a la izquierda, octales, hexadecimales en mayúsculas, cadenas intmax_t, ptrdiff_t, wchar_t C, ancho variable y precisión) en PyUnicode_FromFormat() y PyUnicode_FromFormatV(). (Aportado por Serhiy Storchaka en gh-98836.)

  • Un carácter de formato no reconocido en PyUnicode_FromFormat() y PyUnicode_FromFormatV() ahora establece un SystemError. En versiones anteriores, provocaba que el resto de la cadena de formato se copiara tal cual en la cadena de resultado y se descartaran los argumentos adicionales. (Aportado por Serhiy Storchaka en gh-95781.)

  • Se corrigió la ubicación incorrecta de los letreros en PyUnicode_FromFormat() y PyUnicode_FromFormatV(). (Aportado por Philip Georgi en gh-95504.)

  • Las clases de extensión que deseen agregar un __dict__ o una ranura de referencia débil deben usar Py_TPFLAGS_MANAGED_DICT y Py_TPFLAGS_MANAGED_WEAKREF en lugar de tp_dictoffset y tp_weaklistoffset, respectivamente. El uso de tp_dictoffset y tp_weaklistoffset aún se admite, pero no es totalmente compatible con la herencia múltiple (gh-95589) y el rendimiento puede ser peor. Las clases que declaran Py_TPFLAGS_MANAGED_DICT deben llamar a _PyObject_VisitManagedDict() y _PyObject_ClearManagedDict() para recorrer y borrar los diccionarios de su instancia. Para borrar referencias débiles, llame a PyObject_ClearWeakRefs(), como antes.

  • La función PyUnicode_FSDecoder() ya no acepta rutas de tipo bytes, como los tipos bytearray y memoryview: solo se acepta el tipo bytes exacto para cadenas de bytes. (Aportado por Victor Stinner en gh-98393.)

  • Las macros Py_CLEAR, Py_SETREF y Py_XSETREF ahora solo evalúan sus argumentos una vez. Si un argumento tiene efectos secundarios, estos efectos secundarios ya no se duplican. (Aportado por Victor Stinner en gh-98724.)

  • El indicador de error del intérprete ahora siempre está normalizado. Esto significa que PyErr_SetObject(), PyErr_SetString() y las otras funciones que configuran el indicador de error ahora normalizan la excepción antes de almacenarla. (Aportado por Mark Shannon en gh-101578.)

  • _Py_RefTotal ya no tiene autoridad y solo se conserva por compatibilidad con ABI. Tenga en cuenta que es un global interno y solo está disponible en compilaciones de depuración. Si lo está utilizando, deberá comenzar a utilizar _Py_GetGlobalRefTotal().

  • Las siguientes funciones ahora seleccionan una metaclase apropiada para el tipo recién creado:

    La creación de clases cuya metaclase anule tp_new está en desuso y en Python 3.14+ no estará permitida. Tenga en cuenta que estas funciones ignoran tp_new de la metaclase, lo que posiblemente permita una inicialización incompleta.

    Tenga en cuenta que PyType_FromMetaclass() (agregado en Python 3.12) ya no permite la creación de clases cuya metaclase anule tp_new (__new__() en Python).

    Dado que tp_new anula casi todo lo que hacen las funciones PyType_From*, las dos son incompatibles entre sí. El comportamiento existente (ignorar la metaclase durante varios pasos de la creación de tipos) no es seguro en general, ya que las (meta)clases suponen que se llamó a tp_new. No existe una solución general sencilla. Uno de los siguientes puede funcionar para usted:

    • Si controlas la metaclase, evita usar tp_new en ella:

      • Si se puede omitir la inicialización, se puede realizar en tp_init.

      • Si no es necesario crear una instancia de la metaclase desde Python, configure su tp_new en NULL usando el indicador Py_TPFLAGS_DISALLOW_INSTANTIATION. Esto lo hace aceptable para funciones PyType_From*.

    • Evite las funciones PyType_From*: si no necesita funciones específicas de C (ranuras o configuración del tamaño de la instancia), cree tipos mediante la metaclase calling.

    • Si know puede omitir tp_new de forma segura, filtre la advertencia de obsolescencia usando warnings.catch_warnings() de Python.

  • PyOS_InputHook y PyOS_ReadlineFunctionPointer ya no se llaman en subinterpreters. Esto se debe a que los clientes generalmente dependen del estado global de todo el proceso (ya que estas devoluciones de llamada no tienen forma de recuperar el estado del módulo de extensión).

    Esto también evita situaciones en las que las extensiones pueden encontrarse ejecutándose en un subintérprete que no admiten (o que aún no se han cargado). Consulte gh-104668 para obtener más información.

  • PyLongObject ha tenido cambios internos para un mejor rendimiento. Aunque las partes internas de PyLongObject son privadas, algunos módulos de extensión las utilizan. Ya no se debe acceder directamente a los campos internos, sino que se deben utilizar las funciones API que comienzan con PyLong_.... Se proporcionan dos nuevas funciones API unstable para un acceso eficiente al valor de PyLongObjects que cabe en una sola palabra de máquina:

  • Ahora se requiere que los asignadores personalizados, configurados a través de PyMem_SetAllocator(), sean seguros para subprocesos, independientemente del dominio de memoria. Los asignadores que no tienen su propio estado, incluidos los «ganchos», no se ven afectados. Si su asignador personalizado aún no es seguro para subprocesos y necesita orientación, cree una nueva incidencia en GitHub y CC @ericsnowcurrently.

Obsoleto

Eliminación pendiente en Python 3.14

Eliminación pendiente en Python 3.15

Eliminación pendiente en versiones futuras

Las siguientes API están obsoletas y se eliminarán, aunque actualmente no hay una fecha programada para su eliminación.

Eliminado

  • Elimine el archivo de encabezado token.h. Nunca hubo ninguna API C de tokenizador público. El archivo de encabezado token.h solo fue diseñado para ser utilizado por componentes internos de Python. (Aportado por Victor Stinner en gh-92651.)

  • Se han eliminado las API Unicode heredadas. Consulte PEP 623 para obtener más detalles.

    • PyUnicode_WCHAR_KIND

    • PyUnicode_AS_UNICODE()

    • PyUnicode_AsUnicode()

    • PyUnicode_AsUnicodeAndSize()

    • PyUnicode_AS_DATA()

    • PyUnicode_FromUnicode()

    • PyUnicode_GET_SIZE()

    • PyUnicode_GetSize()

    • PyUnicode_GET_DATA_SIZE()

  • Elimine la macro de función PyUnicode_InternImmortal(). (Aportado por Victor Stinner en gh-85858.)