Qué hay de nuevo en Python 3.8
******************************

Editor:
   Raymond Hettinger

Este artículo explica las nuevas características de Python 3.8, en
comparación con 3.7. Para obtener los detalles completos, consultar el
registro de cambios.

Python 3.8 fue lanzado el 14 de octubre de 2019.


Resumen -- Aspectos destacados de la versión
============================================


Nuevas características
======================


Expresiones de asignación
-------------------------

La nueva sintaxis ":=" asigna valores a variables como parte de una
expresión más grande. Se le conoce cariñosamente como "el operador
morsa" debido a su parecido con los ojos y colmillos de una morsa.

En el siguiente ejemplo, la expresión de asignación ayuda evitando que
se tenga que llamar a "len()" dos veces:

   if (n := len(a)) > 10:
       print(f"List is too long ({n} elements, expected <= 10)")

Un beneficio similar surge durante la búsqueda de coincidencias
mediante expresiones regulares donde los objetos de coincidencias se
necesitan dos veces, una para comprobar si se produjo una coincidencia
y otra para extraer un subgrupo:

   discount = 0.0
   if (mo := re.search(r'(\d+)% discount', advertisement)):
       discount = float(mo.group(1)) / 100.0

El operador también es útil en bucles while que calculan un valor para
comprobar la terminación del bucle y posteriormente necesitan
nuevamente ese mismo valor en el cuerpo del bucle:

   # Loop over fixed length blocks
   while (block := f.read(256)) != '':
       process(block)

Otra motivación de uso surge en las listas por comprensión en las que
un valor calculado en una condición de filtrado también se necesita en
el cuerpo de la expresión:

   [clean_name.title() for name in names
    if (clean_name := normalize('NFC', name)) in allowed_names]

Intenta limitar el uso del "operador morsa" a aquellos casos en los
que reduce la complejidad y mejora la legibilidad del código.

Consultar **PEP 572** para obtener una descripción completa.

(Contribución de Emily Morehouse en bpo-35224.)


Parámetros solo posicionales
----------------------------

Hay una nueva sintaxis para establecer parámetro de función, "/", para
indicar que algunos parámetros de función deben especificarse solo
posicionalmente y no pueden usarse como argumentos por palabra clave.
Esta es la misma notación que muestra "help()" para las funciones de C
anotadas con la herramienta Argument Clinic de Larry Hastings.

En el siguiente ejemplo, los parámetros *a* y *b* son solo
posicionales, mientras que *c* o *d* pueden ser posicionales o por
palabra clave y *e* o *f* deben proporcionarse por palabra clave
exclusivamente:

   def f(a, b, /, c, d, *, e, f):
       print(a, b, c, d, e, f)

La siguiente es una invocación válida:

   f(10, 20, 30, d=40, e=50, f=60)

Sin embargo, estas son invocaciones inválidas:

   f(10, b=20, c=30, d=40, e=50, f=60)   # b cannot be a keyword argument
   f(10, 20, 30, 40, 50, f=60)           # e must be a keyword argument

Un caso de uso de esta notación es permitir que las funciones puras de
Python emulen completamente los comportamientos de las funciones
codificadas en C existentes. Por ejemplo, la función incorporada
"divmod()" no acepta argumentos por palabra clave:

   def divmod(a, b, /):
       "Emulate the built in divmod() function"
       return (a // b, a % b)

Otro caso de uso es excluir los argumentos por palabra clave cuando el
nombre del parámetro no es útil. Por ejemplo, la función incorporada
"len()" tiene la firma "len(obj, /)". Esto excluye llamadas
inoportunas como:

   len(obj='hello')  # The "obj" keyword argument impairs readability

Un beneficio adicional de marcar un parámetro como solo posicional es
que permite cambiar el nombre del parámetro en el futuro sin riesgo de
romper el código del cliente. Por ejemplo, en el módulo "statistics",
el nombre del parámetro *dist* puede cambiarse en el futuro. Esto es
posible gracias a la siguiente especificación de función:

   def quantiles(dist, /, *, n=4, method='exclusive')
       ...

Dado que los parámetros a la izquierda de "/" no se exponen como
posibles palabras clave, los nombres de los parámetros permanecen
disponibles para su uso en "**kwargs":

   >>> def f(a, b, /, **kwargs):
   ...     print(a, b, kwargs)
   ...
   >>> f(10, 20, a=1, b=2, c=3)         # a and b are used in two ways
   10 20 {'a': 1, 'b': 2, 'c': 3}

Esto simplifica enormemente la implementación de funciones y métodos
que necesitan aceptar argumentos por palabra clave arbitrarios. Por
ejemplo, aquí hay un extracto del código del módulo "collections":

   class Counter(dict):

       def __init__(self, iterable=None, /, **kwds):
           # Note "iterable" is a possible keyword argument

Consultar **PEP 570** para obtener una descripción completa.

(Contribución de Pablo Galindo en bpo-36540.)


Caché del sistema de archivos paralelo para archivos de bytecode compilados
---------------------------------------------------------------------------

La nueva configuración "PYTHONPYCACHEPREFIX" (también disponible
mediante la opción "-X" "pycache_prefix") configura la caché implícita
de bytecode para que use un árbol del sistema de archivos paralelo
separado, en lugar de los subdirectorios "__pycache__" predeterminados
dentro cada directorio de origen.

La ubicación de la caché se define en "sys.pycache_prefix" ("None"
indica la ubicación predeterminada en los subdirectorios
"__pycache__").

(Contribución de Carl Meyer en bpo-33499.)


La compilación de depuración usa la misma ABI que la compilación de lanzamiento
-------------------------------------------------------------------------------

Python ahora usa la misma ABI, independientemente de que esté
compilado en modo de lanzamiento o de depuración. En Unix, cuando
Python se compila en modo de depuración, ahora es posible cargar
extensiones C compiladas en modo de lanzamiento y extensiones C
compiladas usando la ABI estable.

Las versiones de lanzamiento y las versiones de depuración ahora son
ABI compatibles: definir la macro "Py_DEBUG" ya no implica la macro
"Py_TRACE_REFS", que introducía la única incompatibilidad de la ABI.
La macro "Py_TRACE_REFS", que agrega la función "sys.getobjects()" y
la variable de entorno "PYTHONDUMPREFS", se puede establecer usando la
nueva opción de compilación "./configure --with-trace-refs".
(Contribución de Victor Stinner en bpo-36465.)

En Unix, las extensiones en C ya no están enlazadas a libpython,
excepto en Android y Cygwin. Ahora es posible que un intérprete Python
enlazado estáticamente cargue una extensión de C creada con una
biblioteca dinámica de Python. (Contribución de Victor Stinner en
bpo-21536.)

En Unix, cuando Python se compila en modo de depuración, la
importación ahora también busca extensiones C compiladas en modo de
lanzamiento y extensiones C compiladas con la ABI estable.
(Contribución de Victor Stinner en bpo-36722.)

Para integrar Python en una aplicación, se debe pasar una nueva opción
"--embed" a "python3-config --libs --embed" para obtener "-lpython3.8"
(enlaza la aplicación a libpython ). Para ser compatible con 3.8 y
versiones anteriores, prueba primero con "python3-config --libs
--embed" y vuelve a usar "python3-config --libs" (sin "--embed") si
falla el comando anterior.

Agrega un módulo pkg-config "python-3.8-embed" para integrar Python en
una aplicación: "pkg-config python-3.8-embed --libs" incluye
"-lpython3.8". Para que sea compatible con 3.8 y versiones anteriores,
primero intenta usar "pkg-config python-X.Y-embed --libs" y vuelve a
"pkg-config python-X.Y --libs" (sin "--embed") si el comando anterior
falla (reemplaza "XY" con la versión de Python).

Por otro lado, "pkg-config python3.8 --libs" ya no contiene
"-lpython3.8". Las extensiones en C no deben estar enlazadas a
libpython (excepto en Android y Cygwin, cuyos casos son manejados por
el script); este cambio no es retrocompatible a propósito.
(Contribución de Victor Stinner en bpo-36721.)


Los f-strings soportan "=" para expresiones autodocumentadas y depuración
-------------------------------------------------------------------------

Se ha agregado un especificador "=" a los *f-string*s. Un f-string
como "f'{expr=}'" se expandirá al texto de la expresión, seguido de un
signo igual y luego la representación de la expresión evaluada. Por
ejemplo:

>>> user = 'eric_idle'
>>> member_since = date(1975, 7, 31)
>>> f'{user=} {member_since=}'
"user='eric_idle' member_since=datetime.date(1975, 7, 31)"

Los especificadores de formato de los f-string usuales permiten un
mayor control sobre como se muestra el resultado de la expresión:

   >>> delta = date.today() - member_since
   >>> f'{user=!s}  {delta.days=:,d}'
   'user=eric_idle  delta.days=16,075'

El especificador "=" mostrará la expresión completa para que se puedan
mostrar los cálculos:

   >>> print(f'{theta=}  {cos(radians(theta))=:.3f}')
   theta=30  cos(radians(theta))=0.866

(Contribución de Eric V. Smith y Larry Hastings en bpo-36817.)


PEP 578: Ganchos de auditoría en tiempo de ejecución de Python
--------------------------------------------------------------

Este PEP agrega un gancho de auditoría y un gancho abierto verificado.
Ambos están disponibles desde Python y desde el código nativo, lo que
permite que las aplicaciones y los frameworks escritos en código
Python puro aprovechen las notificaciones adicionales, al tiempo que
permiten a los integradores o administradores de sistemas implementar
compilaciones de Python donde la auditoría siempre está habilitada.

Consultar **PEP 578** para obtener más detalles.


PEP 587: Configuración de inicialización de Python
--------------------------------------------------

El **PEP 587** agrega una nueva API de C para configurar la
inicialización de Python, proporcionando un control más preciso de
toda la configuración y mejores informes de errores.

Nuevas estructuras:

* "PyConfig"

* "PyPreConfig"

* "PyStatus"

* "PyWideStringList"

Nuevas funciones:

* "PyConfig_Clear()"

* "PyConfig_InitIsolatedConfig()"

* "PyConfig_InitPythonConfig()"

* "PyConfig_Read()"

* "PyConfig_SetArgv()"

* "PyConfig_SetBytesArgv()"

* "PyConfig_SetBytesString()"

* "PyConfig_SetString()"

* "PyPreConfig_InitIsolatedConfig()"

* "PyPreConfig_InitPythonConfig()"

* "PyStatus_Error()"

* "PyStatus_Exception()"

* "PyStatus_Exit()"

* "PyStatus_IsError()"

* "PyStatus_IsExit()"

* "PyStatus_NoMemory()"

* "PyStatus_Ok()"

* "PyWideStringList_Append()"

* "PyWideStringList_Insert()"

* "Py_BytesMain()"

* "Py_ExitStatusException()"

* "Py_InitializeFromConfig()"

* "Py_PreInitialize()"

* "Py_PreInitializeFromArgs()"

* "Py_PreInitializeFromBytesArgs()"

* "Py_RunMain()"

Este PEP también agrega los campos "_PyRuntimeState.preconfig" (tipo
"PyPreConfig") y "PyInterpreterState.config" (tipo "PyConfig") a estas
estructuras internas. "PyInterpreterState.config" se convierte en la
nueva configuración de referencia, reemplazando las variables de
configuración globales y otras variables privadas.

Consultar Configuración de inicialización de Python para la
documentación.

Consultar **PEP 587** para obtener una descripción completa.

(Contribución de Victor Stinner en bpo-36763.)


Vectorcall: un protocolo de invocación rápida para CPython
----------------------------------------------------------

El protocolo "vectorcall" se ha agregado a la API de Python/C. Tiene
como objetivo formalizar las optimizaciones existentes que ya se
realizaron para varias clases. Cualquier tipo de extensión que
implemente un invocable puede utilizar este protocolo.

Actualmente es provisional. El objetivo es hacerlo completamente
público en Python 3.9.

Consultar **PEP 590** para obtener una descripción completa.

(Contribución de Jeroen Demeyer y Mark Shannon en bpo-36974.)


Protocolo 5 de Pickle con búferes de datos fuera de banda
---------------------------------------------------------

Cuando "pickle" se usa para transferir grandes cantidades de datos
entre procesos de Python, con la finalidad de aprovechar el
procesamiento de múltiples núcleos o máquinas, es importante optimizar
la transferencia reduciendo las copias en memoria y posiblemente
aplicando técnicas personalizadas, como la compresión dependiente de
datos.

El protocolo 5 de "pickle" introduce soporte para búferes fuera de
banda, donde los datos compatibles con **PEP 3118** se pueden
transmitir separados del flujo principal de pickle, a discreción de la
capa de comunicación.

Consultar **PEP 574** para obtener una descripción completa.

(Contribución de Antoine Pitrou en bpo-36785.)


Otros cambios en el lenguaje
============================

* La declaración "continue" era ilegal en la cláusula "finally" debido
  a un problema con la implementación. En Python 3.8 se ha eliminado
  esta restricción. (Contribución de Serhiy Storchaka en bpo-32489.)

* Los tipos "bool", "int" y "fractions.Fraction" ahora tienen un
  método "as_integer_ratio()" como el que se encuentra en "float" y
  "decimal.Decimal". Esta extensión menor de la API hace posible
  escribir "numerator, denominator = x.as_integer_ratio()" y hacer que
  funcione con múltiples tipos numéricos. (Contribución de Lisa Roach
  en bpo-33073 y de Raymond Hettinger en bpo-37819.)

* Los constructores de "int", "float" y "complex" ahora usarán el
  método especial "__index__()", si está disponible y el método
  correspondiente "__int__()", "__float__()" o "__complex__()" no está
  disponible. (Contribución de Serhiy Storchaka en bpo-20092.)

* Agregado soporte para escapes "\N{name}" en "expresiones regulares":

     >>> notice = 'Copyright © 2019'
     >>> copyright_year_pattern = re.compile(r'\N{copyright sign}\s*(\d{4})')
     >>> int(copyright_year_pattern.search(notice).group(1))
     2019

  (Contribución de Jonathan Eunice y Serhiy Storchaka in bpo-30688.)

* Los diccionarios y sus vistas ahora se pueden iterar en orden
  inverso de inserción usando "reversed()". (Contribución de Rémi
  Lapeyre en bpo-33462.)

* La sintaxis permitida para los nombres por palabra clave en las
  llamadas a funciones se ha restringido aún más. En particular,
  "f((keyword)=arg)" ya no está permitido. Nunca se tuvo intención de
  permitir algo más que un simple nombre en el lado izquierdo de un
  término de asignación de argumento por palabra clave. (Contribución
  de Benjamin Peterson en bpo-34641.)

* El desempaquetado de iterables generalizado en declaraciones "yield"
  y "return" ya no requiere ser encerrado entre paréntesis. Esto hace
  que la sintaxis de *yield* y *return* se asemeje más a la sintaxis
  normal de asignación:

     >>> def parse(family):
             lastname, *members = family.split()
             return lastname.upper(), *members

     >>> parse('simpsons homer marge bart lisa sally')
     ('SIMPSONS', 'homer', 'marge', 'bart', 'lisa', 'sally')

  (Contribución de David Cuthbert y Jordan Chapman en bpo-32117.)

* Cuando falta una coma en el código, como en "[(10, 20) (30, 40)]",
  el compilador muestra un "SyntaxWarning" con una sugerencia útil.
  Esto representa una mejora con respecto a la implementación previa
  en la que solo se mostraba un "TypeError" indicando que la primera
  tupla no era invocable. (Contribución de Serhiy Storchaka en
  bpo-15248.)

* Las operaciones aritméticas entre subclases de "datetime.date" o
  "datetime.datetime" y "datetime.timedelta" ahora retornan una
  instancia de la subclase, en lugar de la clase base. Esto también
  afecta al tipo de retorno de las operaciones cuya implementación
  (directa o indirectamente) usa la aritmética de
  "datetime.timedelta", como "astimezone()". (Contribución de Paul
  Ganssle en bpo-32417.)

* Cuando el intérprete de Python es interrumpido por Ctrl-C (SIGINT) y
  la excepción "KeyboardInterrupt" resultante no se detecta, el
  proceso de Python ahora termina su ejecución a través de una señal
  SIGINT o con el código de salida correcto, de modo que el proceso
  que lo invocó puede detectar que murió debido a Ctrl-C. Los shells
  en POSIX y Windows usan esto para terminar la ejecución de los
  scripts en sesiones interactivas de forma correcta. (Contribución de
  Google a través de Gregory P. Smith en bpo-1054041.)

* Algunos estilos de programación avanzados requieren actualizar el
  objeto "types.CodeType" para una función ya existente. Dado que los
  objetos de código son inmutables, es necesario crear un nuevo objeto
  de código, que sea modelado a partir del objeto de código existente.
  Con 19 parámetros, esto era algo tedioso. Ahora, el nuevo método
  "replace()" hace posible crear un clon con algunos parámetros
  alterados.

  Aquí hay un ejemplo que modifica la función "statistics.mean()" para
  evitar que el parámetro *data* se use como un argumento por palabra
  clave:

     >>> from statistics import mean
     >>> mean(data=[10, 20, 90])
     40
     >>> mean.__code__ = mean.__code__.replace(co_posonlyargcount=1)
     >>> mean(data=[10, 20, 90])
     Traceback (most recent call last):
       ...
     TypeError: mean() got some positional-only arguments passed as keyword arguments: 'data'

  (Contribución de Victor Stinner en bpo-37032.)

* Para enteros, la forma de tres argumentos de la función "pow()"
  ahora permite que el exponente sea negativo en el caso de que la
  base y el módulo sean primos relativos (coprimos). Luego calcula un
  inverso modular a la base cuando el exponente es "-1" y una potencia
  adecuada de ese inverso en el caso de otros exponentes negativos.
  Por ejemplo, para calcular el inverso multiplicativo de 38 módulo
  137, escribe:

     >>> pow(38, -1, 137)
     119
     >>> 119 * 38 % 137
     1

  Los inversos modulares surgen de la solución de ecuaciones
  diofánticas lineales. Por ejemplo, para encontrar soluciones enteras
  para "4258𝑥 + 147𝑦 = 369", primero debes reescribirla como "4258𝑥 ≡
  369 (mod 147)" y luego resolver:

  >>> x = 369 * pow(4258, -1, 147) % 147
  >>> y = (4258 * x - 369) // -147
  >>> 4258 * x + 147 * y
  369

  (Contribución de Mark Dickinson en bpo-36027.)

* Las compresiones de diccionarios se han sincronizado con los
  literales de diccionario para que primero se calcule la clave y
  posteriormente el valor:

     >>> # Dict comprehension
     >>> cast = {input('role? '): input('actor? ') for i in range(2)}
     role? King Arthur
     actor? Chapman
     role? Black Knight
     actor? Cleese

     >>> # Dict literal
     >>> cast = {input('role? '): input('actor? ')}
     role? Sir Robin
     actor? Eric Idle

  Este orden de ejecución garantizado es especialmente útil en las
  expresiones de asignación porque las variables asignadas en la
  expresión de la clave estarán disponibles en la expresión del valor:

     >>> names = ['Martin von Löwis', 'Łukasz Langa', 'Walter Dörwald']
     >>> {(n := normalize('NFC', name)).casefold() : n for name in names}
     {'martin von löwis': 'Martin von Löwis',
      'łukasz langa': 'Łukasz Langa',
      'walter dörwald': 'Walter Dörwald'}

  (Contribución de Jörn Heissler en bpo-35224.)

* El método "object.__reduce__()" ahora puede retornar una tupla con
  una longitud que va desde los dos a los seis elementos.
  Anteriormente, el límite era cinco. El nuevo sexto elemento opcional
  es un invocable con una firma "(obj, state)". Esto permite el
  control directo sobre el comportamiento de actualización de estado
  de un objeto específico. Si no es *None*, este invocable tendrá
  prioridad sobre el método "__setstate__()" del objeto. (Contribución
  de Pierre Glaser y Olivier Grisel en bpo-35900.)


Nuevos módulos
==============

* El nuevo módulo "importlib.metadata" proporciona soporte
  (provisional) para leer metadatos de paquetes de terceros. Por
  ejemplo, puede extraer el número de versión de un paquete instalado,
  la lista de puntos de entrada y más:

     >>> # Note following example requires that the popular "requests"
     >>> # package has been installed.
     >>>
     >>> from importlib.metadata import version, requires, files
     >>> version('requests')
     '2.22.0'
     >>> list(requires('requests'))
     ['chardet (<3.1.0,>=3.0.2)']
     >>> list(files('requests'))[:5]
     [PackagePath('requests-2.22.0.dist-info/INSTALLER'),
      PackagePath('requests-2.22.0.dist-info/LICENSE'),
      PackagePath('requests-2.22.0.dist-info/METADATA'),
      PackagePath('requests-2.22.0.dist-info/RECORD'),
      PackagePath('requests-2.22.0.dist-info/WHEEL')]

  (Contribución de Barry Warsaw y Jason R. Coombs en bpo-34632.)


Módulos mejorados
=================


ast
---

Los nodos de AST ahora disponen de los atributos "end_lineno" y
"end_col_offset", que proporcionan la localización precisa del final
del nodo. (Esto solo se aplica a los nodos que tienen los atributos
"lineno" y "col_offset".)

La nueva función "ast.get_source_segment()" retorna el código fuente
de un nodo AST específico.

(Contribución de Ivan Levkivskyi en bpo-33416.)

La función "ast.parse()" tiene algunos flags nuevos:

* "type_comments=True" causa que la función retorne el texto de los
  comentarios de tipo especificados en **PEP 484** y **PEP 526**
  asociados con ciertos nodos AST;

* "mode='func_type'" puede usarse para realizar un análisis sintáctico
  de los "comentarios de tipo de firma" de **PEP 484** (retornados por
  los nodos AST de definición de funciones);

* "feature_version=(3, N)" permite especificar una versión de Python 3
  previa. Por ejemplo, "feature_version=(3, 4)" hará que se trate a
  "async" y "await" como palabras no reservadas.

(Contribución de Guido van Rossum en bpo-35766.)


asyncio
-------

"asyncio.run()" ha pasado de la API provisional a la estable. Esta
función se puede utilizar para ejecutar una *coroutine* y retornar el
resultado mientras se gestiona automáticamente el bucle de eventos.
Por ejemplo:

   import asyncio

   async def main():
       await asyncio.sleep(0)
       return 42

   asyncio.run(main())

Esto es *aproximadamente* equivalente a:

   import asyncio

   async def main():
       await asyncio.sleep(0)
       return 42

   loop = asyncio.new_event_loop()
   asyncio.set_event_loop(loop)
   try:
       loop.run_until_complete(main())
   finally:
       asyncio.set_event_loop(None)
       loop.close()

La implementación real es significativamente más compleja. Por lo
tanto, "asyncio.run()" debería ser la forma preferida de ejecutar
programas asyncio.

(Contribución de Yury Selivanov en bpo-32314.)

La ejecución de "python -m asyncio" lanza un REPL asincrónico de forma
nativa. Esto permite una rápida experimentación con código que tiene
un nivel "await" superior. Ya no es necesario llamar directamente a
"asyncio.run()", lo que generaría un nuevo ciclo de eventos en cada
invocación:

   $ python -m asyncio
   asyncio REPL 3.8.0
   Use "await" directly instead of "asyncio.run()".
   Type "help", "copyright", "credits" or "license" for more information.
   >>> import asyncio
   >>> await asyncio.sleep(10, result='hello')
   hello

(Contribución de Yury Selivanov en bpo-37028.)

The exception "asyncio.CancelledError" now inherits from
"BaseException" rather than "Exception" and no longer inherits from
"concurrent.futures.CancelledError". (Contributed by Yury Selivanov in
bpo-32528.)

En Windows, el ciclo de eventos predeterminado ahora es
"ProactorEventLoop". (Contribución de Victor Stinner en bpo-34687.)

"ProactorEventLoop" ahora también es compatible con UDP. (Contribución
de Adam Meily y Andrew Svetlov en bpo-29883.)

"ProactorEventLoop" ahora puede ser interrumpido por
"KeyboardInterrupt" ("CTRL+C"). (Contribución de Vladimir Matveev en
bpo-23057.)

Se ha agregado "asyncio.Task.get_coro()" para obtener la corrutina
envuelta dentro de "asyncio.Task". (Contribución de Alex Grönholm en
bpo-36999.)

Las tareas de Asyncio ahora se pueden nombrar, ya sea pasando el
argumento por palabra clave "name" a "asyncio.create_task()" o al
método "create_task()" del bucle de eventos, o invocando al método
"set_name()" en el objeto de tarea. El nombre de la tarea es visible
en la salida de "repr()" de "asyncio.Task" y también se puede
recuperar usando el método "get_name()". (Contribución de Alex
Grönholm en bpo-34270.)

Se agregó soporte para Happy Eyeballs a
"asyncio.loop.create_connection()". Para especificar el
comportamiento, se han agregado dos nuevos parámetros:
*happy_eyeballs_delay* e *interleave*. El algoritmo Happy Eyeballs
mejora la capacidad de respuesta en aplicaciones que admiten IPv4 e
IPv6 al intentar conectarse simultáneamente utilizando ambos.
(Contribución de twisteroid ambassador en bpo-33530.)


builtins
--------

La función incorporada "compile()" se ha mejorado para que acepte el
flag "ast.PyCF_ALLOW_TOP_LEVEL_AWAIT". Si se pasa este nuevo flag,
"compile()" permitirá construcciones de nivel superior "await", "async
for" y "async with", que normalmente se consideran sintaxis inválida.
El objeto de código asíncrono marcado con el flag "CO_COROUTINE" puede
ser retornado. (Contribución de Matthias Bussonnier en bpo-34616.)


collections
-----------

El método "_asdict()" para "collections.namedtuple()" ahora retorna
una instancia de "dict" en lugar de una de "collections.OrderedDict".
Esto funciona porque se garantiza que los diccionarios regulares
mantienen el orden de inserción desde Python 3.7. Si se requieren las
características adicionales de "OrderedDict", la solución sugerida es
realizar una conversión del resultado al tipo deseado:
"OrderedDict(nt._asdict())". (Contribución de Raymond Hettinger en
bpo-35864.)


cProfile
--------

La clase "cProfile.Profile" ahora puede usarse como gestor de
contexto. Ahora se puede perfilar un bloque de código ejecutando:

   import cProfile

   with cProfile.Profile() as profiler:
         # code to be profiled
         ...

(Contribución de Scott Sanderson en bpo-29235.)


csv
---

"csv.DictReader" ahora retorna instancias de "dict" en lugar de
"collections.OrderedDict". La herramienta ahora es más rápida y usa
menos memoria, mientras conserva el orden de los campos. (Contribución
de Michael Selik en bpo-34003.)


curses
------

Se agregó una nueva variable que contiene información de versión
estructurada para la biblioteca ncurses subyacente: "ncurses_version".
(Contribución de Serhiy Storchaka en bpo-31680.)


ctypes
------

En Windows, "CDLL" y sus subclases ahora aceptan un parámetro
*winmode* para especificar flags para la invocación subyacente de
"LoadLibraryEx". Los flags predeterminados están establecidos para
cargar solo las dependencias de DLL desde ubicaciones confiables,
incluida la ruta donde se almacena la DLL (si se usa una ruta completa
o parcial para cargar la DLL inicial) y las rutas agregadas por
"add_dll_directory()" . (Contribución de Steve Dower en bpo-36085.)


datetime
--------

Se agregaron nuevos constructores alternativos
"datetime.date.fromisocalendar()" y
"datetime.datetime.fromisocalendar()", que construyen objetos "date" y
"datetime" respectivamente con el año, número de semana y día de la
semana de la fecha del calendario ISO. Estos son el inverso del método
"isocalendar" de cada clase. (Contribución de Paul Ganssle en
bpo-36004.)


functools
---------

"functools.lru_cache()" ahora se puede usar como un decorador directo
en lugar de como una función que retorna un decorador. De forma que
ambos son compatibles ahora:

   @lru_cache
   def f(x):
       ...

   @lru_cache(maxsize=256)
   def f(x):
       ...

(Contribución de Raymond Hettinger en bpo-36772.)

Se ha agregado un nuevo decorador "functools.cached_property()", para
propiedades calculadas almacenadas en caché durante toda la vida útil
de la instancia.

   import functools
   import statistics

   class Dataset:
      def __init__(self, sequence_of_numbers):
         self.data = sequence_of_numbers

      @functools.cached_property
      def variance(self):
         return statistics.variance(self.data)

(Contribución de Carl Meyer en bpo-21145.)

Se ha agregado un nuevo decorador "functools.singledispatchmethod()"
que convierte métodos en *funciones genéricas* usando *single
dispatch*:

   from functools import singledispatchmethod
   from contextlib import suppress

   class TaskManager:

       def __init__(self, tasks):
           self.tasks = list(tasks)

       @singledispatchmethod
       def discard(self, value):
           with suppress(ValueError):
               self.tasks.remove(value)

       @discard.register(list)
       def _(self, tasks):
           targets = set(tasks)
           self.tasks = [x for x in self.tasks if x not in targets]

(Contribución de Ethan Smith en bpo-32380)


gc
--

"get_objects()" ahora puede recibir un parámetro opcional *generation*
que indica la generación de la que recolectar objetos. (Contribución
de Pablo Galindo en bpo-36016.)


gettext
-------

Agregado "pgettext()" y sus variantes. (Contribución de Franz Glasner,
Éric Araujo y Cheryl Sabella en bpo-2504.)


gzip
----

Se ha agregó el parámetro *mtime* a "gzip.compress()" para una salida
reproducible. (Contribución de Guo Ci Teo en bpo-34898.)

Una excepción "BadGzipFile" es lanzada ahora, en lugar de "OSError",
para ciertos tipos de archivos gzip no válidos o corruptos.
(Contribución de Filip Gruszczyński, Michele Orrù y Zackery Spytz en
bpo-6584.)


IDLE e idlelib
--------------

Las salidas superiores a N líneas (50 por defecto) se pliegan en un
botón. N se puede cambiar en la sección PyShell de la página General
del cuadro de diálogo Settings. Se pueden plegar menos líneas, pero
posiblemente más largas, haciendo clic derecho en la salida. La salida
plegada se puede expandir en su lugar haciendo doble clic en el botón
o en el portapapeles o en una ventana separada haciendo clic derecho
en el botón. (Contribución de Tal Einat en bpo-1529353.)

Se ha agregado "Run Customized" al menú Run para ejecutar un módulo
con configuraciones personalizadas. Cualquier argumento de la línea de
comandos ingresado se agrega a sys.argv. Además, vuelven a aparecer en
el cuadro para la próxima ejecución personalizada. También se puede
suprimir el reinicio normal del módulo principal de la Shell.
(Contribución de Cheryl Sabella, Terry Jan Reedy y otros en bpo-5680 y
bpo-37627.)

Se agregaron números de línea opcionales para las ventanas del editor
IDLE. Las ventanas se abren sin números de línea, a menos que se
establezca lo contrario en la pestaña General del cuadro de diálogo de
configuración. Los números de línea de una ventana existente se
muestran y ocultan en el menú Options. (Contribución de Tal Einat y
Saimadhav Heblikar en bpo-17535.)

La codificación nativa del sistema operativo ahora se usa para
convertir entre cadenas de Python y objetos Tcl. Esto permite que el
IDLE funcione con emoji y otros caracteres que no son BMP. Estos
caracteres se pueden mostrar o copiar y pegar en ,o desde, el
portapapeles. Convertir cadenas de Tcl a Python y viceversa ahora
nunca falla. (Mucha gente trabajó en esto durante ocho años, pero el
problema finalmente lo resolvió Serhiy Storchaka en bpo-13153.)

New in 3.8.1:

Add option to toggle cursor blink off.  (Contributed by Zackery Spytz
in bpo-4603.)

Escape key now closes IDLE completion windows.  (Contributed by Johnny
Najera in bpo-38944.)

Los cambios anteriores se han portado a las versiones de mantenimiento
de Python 3.7.

Add keywords to module name completion list.  (Contributed by Terry J.
Reedy in bpo-37765.)


inspect
-------

La función "inspect.getdoc()" puede ahora encontrar cadenas de
documentación para "__slots__" si el este atributo es un "dict" cuyos
valores son las cadenas de documentación. Esto proporciona opciones de
documentación similares a las que ya tenemos para "property()",
"classmethod()" y "staticmethod()":

   class AudioClip:
       __slots__ = {'bit_rate': 'expressed in kilohertz to one decimal place',
                    'duration': 'in seconds, rounded up to an integer'}
       def __init__(self, bit_rate, duration):
           self.bit_rate = round(bit_rate / 1000.0, 1)
           self.duration = ceil(duration)

(Contribución de Raymond Hettinger en bpo-36326.)


io
--

En el modo de desarrollo ("-X" "env") y en la compilación de
depuración, el finalizador "io.IOBase" ahora registra la excepción si
falla el método "close()". La excepción se ignora silenciosamente de
forma predeterminada en la compilación de lanzamiento. (Contribución
de Victor Stinner en bpo-18748.)


itertools
---------

Se ha agregado un argumento por palabra clave opcional *initial* a la
función "itertools.accumulate()" para permitir especificar un valor
inicial:

   >>> from itertools import accumulate
   >>> list(accumulate([10, 5, 30, 15], initial=1000))
   [1000, 1010, 1015, 1045, 1060]

(Contribución de Lisa Roach en bpo-34659.)


json.tool
---------

Agregadas las opciones "--json-lines" para analizar sintácticamente
cada línea de entrada como un objeto JSON separado. (Contribución de
Weipeng Hong en bpo-31553.)


logging
-------

Agregado un argumento por palabra clave *force* a la función
"logging.basicConfig()". Cuando se establece en verdadero, cualquier
controlador existente adjunto al registrador (logger) raíz se elimina
y se cierra antes de realizar la configuración especificada por los
otros argumentos.

Esto resuelve un problema de larga data. Una vez que se había invocado
a un registrador o a *basicConfig()*, las invocaciones posteriores a
*basicConfig()* se ignoraban en silencio. Esto dificultaba la
actualización, la experimentación o la instrucción de las diversas
opciones de configuración de registro mediante el interprete
interactivo o el bloc de notas de Jupyter.

(Sugerencia de Raymond Hettinger, implementación de Dong-hee Na y
revisión de Vinay Sajip en bpo-33897.)


math
----

Se ha agregado la nueva función "math.dist()" para calcular la
distancia euclidiana entre dos puntos. (Contribución de Raymond
Hettinger en bpo-33089.)

Se ha expandido la función "math.hypot()" para manejar múltiples
dimensiones. Anteriormente, solo admitía dos dimensiones.
(Contribución de Raymond Hettinger en bpo-33089.)

Agregada una nueva función, "math.prod()", como función análoga a
"sum()", que retorna el producto de todos los elementos de un iterable
de números partiendo de un valor de inicio (*start*) (por defecto: 1):

   >>> prior = 0.8
   >>> likelihoods = [0.625, 0.84, 0.30]
   >>> math.prod(likelihoods, start=prior)
   0.126

(Contribución de Pablo Galindo en bpo-35606.)

Agregadas dos nuevas funciones combinatorias, "math.perm()" y
"math.comb()":

   >>> math.perm(10, 3)    # Permutations of 10 things taken 3 at a time
   720
   >>> math.comb(10, 3)    # Combinations of 10 things taken 3 at a time
   120

(Contribución de Yash Aggarwal, Keller Fuchs, Serhiy Storchaka y
Raymond Hettinger en bpo-37128, bpo-37178 y bpo-35431.)

Se ha agregada una nueva función "math.isqrt()" para calcular raíces
cuadradas enteras precisas sin conversión a coma flotante. La nueva
función admite números enteros arbitrariamente grandes. Es más rápida
que "floor(sqrt(n))" pero más lenta que "math.sqrt()":

   >>> r = 650320427
   >>> s = r ** 2
   >>> isqrt(s - 1)         # correct
   650320426
   >>> floor(sqrt(s - 1))   # incorrect
   650320427

(Contribución de Mark Dickinson en bpo-36887.)

La función "math.factorial()" ya no acepta argumentos que no sean
similares a enteros. (Contribución de Pablo Galindo en bpo-33083.)


mmap
----

La clase "mmap.mmap" ahora tiene un método "madvise()" para acceder a
la llamada al sistema "madvise()". (Contribución de Zackery Spytz en
bpo-32941.)


multiprocessing
---------------

Agregado el nuevo módulo "multiprocessing.shared_memory".
(Contribución de Davin Potts en bpo-35813.)

En macOS, el método de inicio *spawn* se usa ahora por defecto.
(Contribución de Victor Stinner en bpo-33725.)


os
--

Se agregó una nueva función "add_dll_directory()" en Windows para
proporcionar rutas de búsqueda adicionales para las dependencias
nativas al importar módulos de extensión o al cargar archivos DLL
utilizando "ctypes". (Contribución de Steve Dower en bpo-36085.)

Se agregó una nueva función "os.memfd_create()" para envolver la
llamada al sistema "memfd_create()". (Contribución de Zackery Spytz y
Christian Heimes en bpo-26836.)

En Windows, gran parte de la lógica manual para manejar los puntos de
reinterpretación (incluidos los enlaces simbólicos y las uniones de
directorios) se ha delegado al sistema operativo. Específicamente,
"os.stat()" ahora se encargará de todo lo que sea compatible con el
sistema operativo, mientras que "os.lstat()" solo abrirá puntos de
reinterpretación que se identifican como "sustitutos de nombre" y el
resto se abrirán mediante "os.stat()". En todos los casos,
"stat_result.st_mode" solo tendrá establecido "S_IFLNK" para enlaces
simbólicos y no para otros tipos de puntos de reinterpretación. Para
identificar otros tipos de puntos de reinterpretación, verifica el
nuevo atributo "stat_result.st_reparse_tag".

En Windows, "os.readlink()" ahora puede leer uniones de directorio.
Ten en cuenta que "islink()" retornará "False" para las uniones de
directorios, por lo que el código que comprueba en primer lugar
"islink" continuará tratando las uniones como directorios, mientras
que el código que maneja los errores de "os.readlink()" ahora puede
tratar las uniones como enlaces.

(Contribución de Steve Dower en bpo-37834.)

As of 3.8.20, "os.mkdir()" and "os.makedirs()" on Windows now support
passing a *mode* value of "0o700" to apply access control to the new
directory. This implicitly affects "tempfile.mkdtemp()" and is a
mitigation for CVE-2024-4030. Other values for *mode* continue to be
ignored. (Contributed by Steve Dower in gh-118486.)


os.path
-------

Las funciones de "os.path" que retornan un resultado booleano como
"exists()", "lexists()", "isdir()", "isfile()", "islink()" e
"ismount()" ahora retornan "False" en lugar de lanzar una excepción
"ValueError", o sus subclases "UnicodeEncodeError" y
"UnicodeDecodeError", para rutas que contienen caracteres o bytes
irrepresentables a nivel del sistema operativo. (Contribución de
Serhiy Storchaka en bpo-33721.)

"expanduser()" en Windows ahora usa preferentemente la variable de
entorno "USERPROFILE" y no usa "HOME", que normalmente no está
establecido para cuentas de usuario normales. (Contribución de Anthony
Sottile en bpo-36264.)

"isdir()" en Windows ya no retorna "True" para un enlace a un
directorio no existente.

"realpath()" en Windows ahora resuelve puntos de reinterpretación
(reparse points), incluidos enlaces simbólicos y uniones de
directorio.

(Contribución de Steve Dower en bpo-37834.)


pathlib
-------

Los métodos del módulo "pathlib.Path" que retornan un resultado
booleano, como "exists()", "is_dir()", "is_file()", "is_mount()",
"is_symlink()", "is_block_device()", "is_char_device()", "is_fifo()" o
"is_socket()", ahora retornan "False" en vez de lanzar una excepción
"ValueError" o su subclase "UnicodeEncodeError" para rutas que
contienen caracteres no representables a nivel del sistema operativo.
(Contribución de Serhiy Storchaka en bpo-33721.)

Agregado "pathlib.Path.link_to()" que crea un enlace duro apuntando a
una ruta. (Contribución de Joannah Nanjekye en bpo-26978)


pickle
------

Las extensiones de "pickle" que subclasifican la clase optimizada de C
"Pickler" ahora pueden anular la lógica de pickling de funciones y
clases definiendo el método especial "reducer_override()".
(Contribución de Pierre Glaser y Olivier Grisel en bpo-35900.)


plistlib
--------

Se ha agregado la nueva clase "plistlib.UID" y se ha habilitado el
soporte para leer y escribir plists binarios codificados por
NSKeyedArchiver. (Contribución de Jon Janzen en bpo-26707.)


pprint
------

Se ha agregado el parámetro *sort_dicts* a varias funciones del módulo
"pprint". De forma predeterminada, esas funciones continúan ordenando
los diccionarios antes de procesarlos o imprimirlos. Sin embargo, si
*sort_dicts* se establece en falso, los diccionarios conservan el
orden en que se insertaron las claves. Esto puede resultar útil para
la comparación con entradas JSON durante la depuración.

Además, hay una nueva función de conveniencia, "pprint.pp()", que es
igual que "pprint.pprint()" pero con *sort_dicts* establecido en
"False" por defecto:

   >>> from pprint import pprint, pp
   >>> d = dict(source='input.txt', operation='filter', destination='output.txt')
   >>> pp(d, width=40)                  # Original order
   {'source': 'input.txt',
    'operation': 'filter',
    'destination': 'output.txt'}
   >>> pprint(d, width=40)              # Keys sorted alphabetically
   {'destination': 'output.txt',
    'operation': 'filter',
    'source': 'input.txt'}

(Contribución de Rémi Lapeyre en bpo-30670.)


py_compile
----------

"py_compile.compile()" ahora admite el modo silencioso. (Contribución
de Joannah Nanjekye en bpo-22640.)


shlex
-----

La nueva función "shlex.join()" actúa a la inversa de "shlex.split()".
(Contribución de Bo Bayles en bpo-32102.)


shutil
------

"shutil.copytree()" ahora acepta el nuevo argumento por palabra clave
"dirs_exist_ok". (Contribución de Josh Bronson en bpo-20849.)

"shutil.make_archive()" ahora usa por defecto el formato pax moderno
(POSIX.1-2001) para nuevos archivos para mejorar la portabilidad y la
conformidad con los estándares, heredado el cambio correspondiente del
módulo "tarfile". (Contribución de C.A.M. Gerlach en bpo-30661.)

"shutil.rmtree()" en Windows ahora elimina las uniones de directorio
sin eliminar recursivamente su contenido primero. (Contribución de
Steve Dower en bpo-37834.)


socket
------

Se han agregado las funciones de conveniencia "create_server()" y
"has_dualstack_ipv6()" para automatizar las tareas necesarias
involucradas al crear un socket servidor, incluida la aceptación de
conexiones IPv4 e IPv6 en el mismo socket . (Contribución de Giampaolo
Rodolà en bpo-17561.)

Las funciones "socket.if_nameindex()", "socket.if_nametoindex()" y
"socket.if_indextoname()" se han implementado en Windows.
(Contribución de Zackery Spytz en bpo-37007.)


ssl
---

Se ha agregado "post_handshake_auth" para habilitar y
"verify_client_post_handshake()" para iniciar la autenticación tras el
establecimiento de la comunicación en TLS 1.3. (Contribución de
Christian Heimes en bpo-34670.)


statistics
----------

Se ha agregado "statistics.fmean()" como una variante de punto
flotante más rápida de "statistics.mean()". (Contribución de Raymond
Hettinger y Steven D'Aprano en bpo-35904.)

Se ha agregado "statistics.geometric_mean()" (Contribución de Raymond
Hettinger en bpo-27181.)

Se ha agregado "statistics.multimode()" que retorna una lista con los
valores más comunes. (Contribución de Raymond Hettinger en bpo-35892.)

Se ha agregado "statistics.quantiles()" que divide datos o una
distribución en intervalos equiprobables (por ejemplo, cuartiles,
deciles o percentiles). (Contribución de Raymond Hettinger en
bpo-36546.)

Se ha agregado "statistics.NormalDist", una herramienta para crear y
manipular distribuciones normales de una variable aleatoria.
(Contribución de Raymond Hettinger en bpo-36018.)

   >>> temperature_feb = NormalDist.from_samples([4, 12, -3, 2, 7, 14])
   >>> temperature_feb.mean
   6.0
   >>> temperature_feb.stdev
   6.356099432828281

   >>> temperature_feb.cdf(3)            # Chance of being under 3 degrees
   0.3184678262814532
   >>> # Relative chance of being 7 degrees versus 10 degrees
   >>> temperature_feb.pdf(7) / temperature_feb.pdf(10)
   1.2039930378537762

   >>> el_niño = NormalDist(4, 2.5)
   >>> temperature_feb += el_niño        # Add in a climate effect
   >>> temperature_feb
   NormalDist(mu=10.0, sigma=6.830080526611674)

   >>> temperature_feb * (9/5) + 32      # Convert to Fahrenheit
   NormalDist(mu=50.0, sigma=12.294144947901014)
   >>> temperature_feb.samples(3)        # Generate random samples
   [7.672102882379219, 12.000027119750287, 4.647488369766392]


sys
---

Se ha agregado la nueva función "sys.unraisablehook()" que se puede
anular para controlar cómo se manejan las "excepciones no lanzables".
Se llama cuando se ha producido una excepción, pero Python no tiene
forma de manejarla. Por ejemplo, cuando un destructor genera una
excepción o durante la recolección de basura ("gc.collect()").
(Contribución de Victor Stinner en bpo-36829.)


tarfile
-------

El módulo "tarfile" ahora tiene por defecto el formato pax moderno
(POSIX.1-2001) para nuevos archivos, en lugar del anterior específico
de GNU. Esto mejora la portabilidad multiplataforma con una
codificación consistente (UTF-8) en un formato estandarizado y
extensible, y ofrece otros varios beneficios. (Contribución de C.A.M.
Gerlach en bpo-36268.)


tempfile
--------

As of 3.8.20 on Windows, the default mode "0o700" used by
"tempfile.mkdtemp()" now limits access to the new directory due to
changes to "os.mkdir()". This is a mitigation for CVE-2024-4030.
(Contributed by Steve Dower in gh-118486.)


threading
---------

Se ha agregado una nueva función "threading.excepthook()" que maneja
las excepciones "threading.Thread.run()" no capturadas. Se puede
anular para controlar cómo se manejan las excepciones
"threading.Thread.run()" no capturadas. (Contribución de Victor
Stinner en bpo-1230540.)

Se han agregado una nueva función "threading.get_native_id()" y un
atributo "native_id" a la clase "threading.Thread". Estos retornan el
Thread ID nativo integral del hilo actual asignado por el kernel. Esta
función solo está disponible en determinadas plataformas, consulta
"get_native_id" para obtener más información. (Contribución de Jake
Tesler en bpo-36084.)


tokenize
--------

El módulo "tokenize" ahora emite implícitamente un token "NEWLINE"
cuando se le proporciona una entrada sin una nueva línea al final.
Este comportamiento ahora coincide con lo que hace internamente el
tokenizador de C. (Contribución de Ammar Askar en bpo-33899.)


tkinter
-------

Se han agregado los métodos "selection_from()", "selection_present()",
"selection_range()" y "selection_to()" a la clase "tkinter.Spinbox".
(Contribución de Juliette Monsel en bpo-34829.)

Se ha agregado el método "moveto()" a la clase "tkinter.Canvas".
(Contribución de Juliette Monsel en bpo-23831.)

La clase "tkinter.PhotoImage" ahora dispone de los métodos
"transparency_get()" y "transparency_set()". (Contribución de Zackery
Spytz en bpo-25451.)


time
----

Se ha agregado el nuevo reloj "CLOCK_UPTIME_RAW" para macOS 10.12.
(Contribución de Joannah Nanjekye en bpo-35702.)


typing
------

Se han incorporado varias características al módulo "typing":

* Un tipo de diccionario con tipos para cada clave. Consultar **PEP
  589** y "typing.TypedDict". TypedDict usa solo claves de cadenas de
  caracteres. De forma predeterminada, se requiere que todas las
  claves estén presentes. Especifica "total=False" para permitir que
  las claves sean opcionales:

     class Location(TypedDict, total=False):
         lat_long: tuple
         grid_square: str
         xy_coordinate: tuple

* Tipos literales. Consultar **PEP 586** y "typing.Literal". Los tipos
  literales indican que un parámetro o valor de retorno está
  restringido a uno o más valores literales específicos:

     def get_status(port: int) -> Literal['connected', 'disconnected']:
         ...

* Variables, funciones, métodos y clases "finales". Consultar **PEP
  591**, "typing.Final" y "typing.final()". El clasificador final
  instruye a un validador estático de tipos para restringir la
  subclasificación, anulación o reasignación:

     pi: Final[float] = 3.1415926536

* Definiciones de protocolo. Consultar **PEP 544**, "typing.Protocol"
  y "typing.runtime_checkable()". ABCs simples como
  "typing.SupportsInt" ahora son subclases de "Protocol" .

* Nueva clase protocolo "typing.SupportsIndex".

* Nuevas funciones "typing.get_origin()" y "typing.get_args()".


unicodedata
-----------

El módulo "unicodedata" ha sido actualizado para usar Unicode 12.1.0.

La nueva función "is_normalized()" puede usarse para verificar que una
cadena está en una forma normal específica, lo que es a menudo mucho
más rápido que normalizar la cadena. (Contribución de Max Belanger,
David Euresti y Greg Price en bpo-32285 y bpo-37966).


unittest
--------

Se ha agregado "AsyncMock" para admitir una versión asincrónica de
"Mock". También se han agregado nuevas funciones de aserción
apropiadas para las pruebas. (Contribución de Lisa Roach en
bpo-26467).

Se ha agregado "addModuleCleanup()" y "addClassCleanup()" a unittest
para admitir limpiezas para "setUpModule()" y "setUpClass()".
(Contribución de Lisa Roach en bpo-24412.)

Varias funciones de aserción simulada ahora también imprimen una lista
de llamadas reales en caso de fallo. (Contribución de Petter
Strandmark en bpo-35047.)

El módulo "unittest" ha obtenido soporte para corrutinas que se
utilizarán como casos de prueba con
"unittest.IsolatedAsyncioTestCase". (Contribución de Andrew Svetlov en
bpo-32972.)

Ejemplo:

   import unittest


   class TestRequest(unittest.IsolatedAsyncioTestCase):

       async def asyncSetUp(self):
           self.connection = await AsyncConnection()

       async def test_get(self):
           response = await self.connection.get("https://example.com")
           self.assertEqual(response.status_code, 200)

       async def asyncTearDown(self):
           await self.connection.close()


   if __name__ == "__main__":
       unittest.main()


venv
----

"venv" ahora incluye un script "Activate.ps1" en todas las plataformas
para activar entornos virtuales en PowerShell Core 6.1. (Contribución
de Brett Cannon en bpo-32718.)


weakref
-------

Los objetos proxy retornados por "debilref.proxy()" ahora admiten los
operadores de multiplicación de matrices "@" y "@=", además de los
otros operadores numéricos. (Contribución de Mark Dickinson en
bpo-36669.)


xml
---

Como mitigación contra DTD y recuperación de entidades externas, los
módulos "xml.dom.minidom" y "xml.sax" ya no procesan entidades
externas de forma predeterminada. (Contribución de Christian Heimes en
bpo-17239.)

Los métodos ".find*()" del módulo "xml.etree.ElementTree" admiten
búsquedas con comodines, como "{*}tag", que ignora el espacio de
nombres, y "{namespace}*", que retorna todas las etiquetas en el
espacio de nombres dado. (Contribución de Stefan Behnel en bpo-28238.)

El módulo "xml.etree.ElementTree" proporciona una nueva función
"–xml.etree.ElementTree.canonicalize()" que implementa C14N 2.0.
(Contribución de Stefan Behnel en bpo-13611.)

El objeto de destino de "xml.etree.ElementTree.XMLParser" puede
recibir eventos de declaración de espacio de nombres a través de los
nuevos métodos de retrollamada "start_ns()" y "end_ns()". Además, el
destino "xml.etree.ElementTree.TreeBuilder" se puede configurar para
procesar eventos sobre comentarios e instrucciones de procesamiento
para incluirlos en el árbol generado. (Contribución de Stefan Behnel
en bpo-36676 y bpo-36673.)


xmlrpc
------

"xmlrpc.client.ServerProxy" ahora admite un argumento por palabra
clave *headers* opcional para una secuencia de encabezados HTTP que se
enviarán con cada solicitud. Entre otras cosas, esto permite
actualizar desde la autenticación básica predeterminada a una
autenticación de sesión más rápida. (Contribución de Cédric Krier en
bpo-35153.)


Optimizaciones
==============

* El módulo "subprocess" ahora puede usar en ciertos casos la función
  "os.posix_spawn()" para mejorar el rendimiento. Actualmente, solo se
  usa en macOS y Linux (usando glibc 2.24 o una versión más reciente)
  y siempre que se cumplan todas estas condiciones:

  * *close_fds* es falso;

  * los parámetros *preexec_fn*, *pass_fds*, *cwd* y
    *start_new_session* no están establecidos;

  * la ruta *executable* contiene un directorio.

  (Contribución de Joannah Nanjekye y Victor Stinner en bpo-35537.)

* "shutil.copyfile()", "shutil.copy()", "shutil.copy2()",
  "shutil.copytree()" y "shutil.move()" usan llamadas al sistema de
  "copia-rápida" específicas de la plataforma en Linux y macOS, con la
  finalidad de copiar ficheros más eficientemente. "copia-rápida"
  significa que la operación de copiado tiene lugar en el propio
  kernel, evitando que Python haga uso de búferes en el espacio de
  usuario como ""outfd.write(infd.read())"". En Windows,
  "shutil.copyfile()" usa un tamaño de búfer predeterminado más grande
  (1 MiB en lugar de 16 KiB) y se usa una variante de
  "shutil.copyfileobj()" basada en "memoryview()". La aceleración al
  copiar un archivo de 512 MiB dentro de la misma partición es de
  aproximadamente +26% en Linux, +50% en macOS y +40% en Windows.
  Además, se consumen muchos menos ciclos de CPU. Consultar la sección
  Operaciones de copia eficientes dependientes de la plataforma.
  (Contribución de Giampaolo Rodolà en bpo-33671.)

* Ahora "shutil.copytree()" usa la función "os.scandir()" y todas las
  funciones de copia que dependen de ella usan el valor en caché de
  "os.stat()". Al copiar un directorio con 8000 archivos, la mejora de
  velocidad es de +9% en Linux, +20% en Windows y +30% en recursos
  compartidos de Windows SMB. Además, el número de llamadas al sistema
  de "os.stat()" se reduce en un 38%, lo que hace que
  "shutil.copytree()" sea más rápida especialmente en sistemas de
  archivos de red. (Contribución de Giampaolo Rodolà en bpo-33695.)

* El protocolo por defecto del módulo "pickle" es ahora el Protocolo
  4, introducido por primera vez en Python 3.4. Ofrece un mejor
  desempeño y un menor tamaño, en comparación con el Protocolo 3
  disponible desde Python 3.0.

* Eliminado un miembro "Py_ssize_t" de "PyGC_Head". El tamaño de todos
  los objetos seguidos por el GC (por ejemplo tuple, list y dict) se
  ha reducido 4 u 8 bytes. (Contribución de Inada Naoki en bpo-33597.)

* La clase "uuid.UUID" ahora usa "__slots__" para reducir su impacto
  en la memoria. (Contribución de Wouter Bolsterlee y Tal Einat en
  bpo-30977.)

* Mejorado el rendimiento de "operator.itemgetter()" en un 33%. Se ha
  optimizado el manejo de argumentos y se ha agregado una ruta rápida
  al caso común de índices enteros no negativos únicos en tuplas (que
  constituye un caso de uso común en la biblioteca estándar).
  (Contribución de Raymond Hettinger en bpo-35664.)

* Se han acelerado las búsquedas de campos en
  "collections.namedtuple()". Ahora son más del doble de rápidas, lo
  que las convierte en la forma más rápida de búsqueda de variables de
  instancia en Python. (Contribución de Raymond Hettinger, Pablo
  Galindo, Joe Jevnik y Serhiy Storchaka en bpo-32492.)

* El constructor de "list" no sobre-asignará el búfer del elemento
  interno si se conoce la longitud de la entrada iterable (es decir,
  si la entrada implementa "__len__"). Esto hace que la lista generada
  sea, en promedio, un 12% más pequeña. (Contribución de Raymond
  Hettinger y Pablo Galindo en bpo-33234.)

* De ha duplicado la velocidad de escritura de variables de clase.
  Antes, cuando se actualizaba un atributo non-dunder, había una
  llamada innecesaria para actualizar slots. (Contribución de Stefan
  Behnel, Pablo Galindo Salgado, Raymond Hettinger, Neil Schemenauer y
  Serhiy Storchaka en bpo-36012.)

* Se ha reducido la sobrecarga de conversión de argumentos pasados a
  muchas funciones y métodos integrados. Esto acelera la llamada a
  algunas funciones y métodos incorporados simples hasta un 20-50%.
  (Contribución de Serhiy Storchaka en bpo-23867, bpo-35582 y
  bpo-36127.)

* La instrucción "LOAD_GLOBAL" ahora utiliza el nuevo mecanismo "per
  opcode cache". Ahora es aproximadamente un 40% más rápida.
  (Contribución de Yury Selivanov e Inada Naoki en bpo-26219.)


Cambios en la compilación y la API de C
=======================================

* El valor predeterminado para "sys.abiflags" es ahora una cadena
  vacía: el flag "m" para pymalloc se ha vuelto innecesario (las
  compilaciones con y sin pymalloc son ABI compatibles) y por lo tanto
  se ha eliminado. (Contribución de Victor Stinner en bpo-36707.)

  Ejemplos del cambio:

  * Solo el programa "python3.8" es instalado, el programa
    "python3.8m" se ha eliminado.

  * Solo el script "python3.8-config" es instalado, el script "python3
    .8m-config" se ha eliminado.

  * El flag "m" se ha eliminado del sufijo de los nombres de archivo
    de las bibliotecas dinámicas: los módulos de extensión de la
    biblioteca estándar, así como los producidos e instalados por
    paquetes de terceros, como los descargados desde PyPI. En Linux,
    por ejemplo, el sufijo ".cpython-37m-x86_64-linux-gnu.so" en
    Python 3.7 se ha convertido en ".cpython-38-x86_64-linux-gnu.so"
    en Python 3.8.

* Los archivos de cabeceras se han reorganizado para separar mejor los
  diferentes tipos de APIs:

  * "Include/*.h" debe ser la API de C portable, pública y estable.

  * "Include/cpython/*.h" debe ser la API de C inestable específica de
    CPython. Una API pública, con alguna API privada marcada con los
    prefijos "_Py" o "_PY".

  * "Include/internal/*.h" es la API de C interna privada, muy
    específica de CPython. Esta API no tiene retro-compatibilidad
    garantizada con versiones anteriores y no debe ser usada fuera de
    CPython. Solo está expuesta para cubrir necesidades muy
    específicas, como es el caso de depuradores y perfiladores, que
    necesitan acceder a los componentes internos de CPython sin llamar
    directamente a las funciones. Esta API es ahora instalada por
    "make install".

  (Contribución de Victor Stinner en bpo-35134 y bpo-35081, trabajo
  iniciado por Eric Snow en Python 3.7.)

* Algunas macros se han convertido a funciones inline estáticas: los
  tipos de los parámetros y el tipo de retorno están bien definidos,
  no entrañan cuestiones que precisen el uso específico de macros y
  las variables tienen ámbito local. Algunos ejemplos:

  * "Py_INCREF()", "Py_DECREF()"

  * "Py_XINCREF()", "Py_XDECREF()"

  * "PyObject_INIT()", "PyObject_INIT_VAR()"

  * Funciones privadas: "_PyObject_GC_TRACK()",
    "_PyObject_GC_UNTRACK()", "_Py_Dealloc()"

  (Contribución de Victor Stinner en bpo-35059.)

* Las funciones "PyByteArray_Init()" y "PyByteArray_Fini()" se han
  eliminado. No eran de utilidad desde Python 2.7.4 y Python 3.2.0,
  cuando fueron excluidas de la API limitada (ABI estable) y dejaron
  de estar documentadas. (Contribución de Victor Stinner en
  bpo-35713.)

* El resultado de "PyExceptionClass_Name()" es ahora de tipo "const
  char *" en vez de "char *". (Contribución de Serhiy Storchaka en
  bpo-33818.)

* La dualidad conformada por "Modules/Setup.dist" y "Modules/Setup" ha
  sido eliminada. Anteriormente, al actualizar el árbol de fuentes de
  CPython, se tenía que copiar manualmente "Modules/Setup.dist"
  (dentro del árbol de fuentes) a "Modules/Setup" (dentro del árbol de
  compilación) para reflejar cualquier cambio en sentido ascendente.
  Esto suponía un pequeño beneficio para los empaquetadores, a
  expensas de una frecuente molestia para los desarrolladores de
  CPython, ya que olvidarse de copiar el archivo podía ocasionar
  fallos de compilación.

  Ahora el sistema de compilación siempre lee desde "Modules/Setup"
  dentro del árbol de fuentes. Se recomienda a las personas que deseen
  personalizar este archivo que mantengan sus cambios en un fork de
  git de CPython o como archivos de parche, como harían con cualquier
  otro cambio en el árbol de fuentes.

  (Contribución de Antoine Pitrou en bpo-32430.)

* Las funciones que convierten un número de Python a un entero de C,
  como "PyLong_AsLong()", y las funciones de análisis de argumentos
  como "PyArg_ParseTuple()" con unidades de formato de conversión de
  enteros como "'i'", ahora usarán el método especial "__index__()" si
  está disponible, en lugar de "__int__()". Una advertencia de
  deprecación se emitirá para aquellos objetos que tengan el método
  "__int__()" pero no el método "__index__()" (como "Decimal" y
  "Fraction"). "PyNumber_Check()" ahora retornará "1" para los objetos
  que implementen "__index__()". "PyNumber_Long()", "PyNumber_Float()"
  y "PyFloat_AsDouble()" ahora también usan el método "__index__()" si
  está disponible. (Contribución de Serhiy Storchaka en bpo-36048 y
  bpo-20092.)

* Los objetos de tipo asignados al montículo ahora aumentarán su
  recuento de referencias en "PyObject_Init()" (y en su macro paralela
  "PyObject_INIT") en lugar de en "PyType_GenericAlloc()". Es posible
  que deban ajustarse los tipos que modifican la asignación o
  desasignación de instancias. (Contribución de Eddie Elizondo en
  bpo-35810.)

* La nueva función "PyCode_NewWithPosOnlyArgs()" permite crear objetos
  de código, al igual que "PyCode_New()", pero con un parámetro
  *posonlyargcount* extra, que permite indicar el número de argumentos
  solo posicionales.

* "Py_SetPath()" ahora establece "sys.executable" en la ruta completa
  del programa ("Py_GetProgramFullPath()"), en vez de en el nombre del
  programa ("Py_GetProgramName()"). (Contribución de Victor Stinner en
  bpo-38234.)


Obsoleto
========

* El comando "bdist_wininst" de distutils está ahora obsoleto, usar
  "bdist_wheel" (paquetes wheel) en su lugar. (Contribución de Victor
  Stinner en bpo-37481.)

* Los métodos "getchildren()" y "getiterator()" del módulo
  "ElementTree" ahora emiten una advertencia "DeprecationWarning", en
  lugar de "PendingDeprecationWarning". Serán eliminados en Python
  3.9. (Contribución de Serhiy Storchaka en bpo-29209.)

* Pasar un objeto a "loop.set_default_executor()" que no sea una
  instancia de "concurrent.futures.ThreadPoolExecutor" está obsoleto y
  será prohibido en Python 3.9. (Contribución de Elvis Pranskevichus
  en bpo-34075.)

* Los métodos "__getitem__()" pertenecientes a las clases
  "xml.dom.pulldom.DOMEventStream", "wsgiref.util.FileWrapper" y
  "fileinput.FileInput" están obsoletos a partir de ahora.

  Las implementaciones de estos métodos han estado ignorando su
  parámetro *index* y retornando el siguiente item en su lugar.
  (Contribución de Berker Peksag en bpo-9372.)

* El atributo "_field_types" de la clase "typing.NamedTuple" está
  ahora obsoleto en favor del atributo "__annotations__", que contiene
  la misma información. (Contribución de Raymond Hettinger en
  bpo-36320.)

* Las clases "Num", "Str", "Bytes", "NameConstant" y "Ellipsis" del
  módulo "ast" están consideradas obsoletas y serán eliminadas en
  versiones futuras de Python. La clase "Constant" debe ser usada en
  su lugar. (Contribución de Serhiy Storchaka en bpo-32892.)

* Los métodos "visit_Num()", "visit_Str()", "visit_Bytes()",
  "visit_NameConstant()" y "visit_Ellipsis()" de la clase
  "ast.NodeVisitor" están obsoletos ahora y serán invocados en
  versiones futuras de Python. Agregar el método "visit_Constant()"
  para manejar todos los nodos constantes. (Contribución de Serhiy
  Storchaka en bpo-36917.)

* El *decorator* "asyncio.coroutine()" está obsoleto y será eliminado
  en Python 3.10. En lugar de "@asyncio.coroutine", se debe usar
  "async def". (Contribución de Andrew Svetlov en bpo-36921.)

* En "asyncio", pasar un argumento *loop* de forma explícita está
  ahora obsoleto y será eliminado en Python 3.10 para las siguientes
  funciones y constructores: "asyncio.sleep()", "asyncio.gather()",
  "asyncio.shield()", "asyncio.wait_for()", "asyncio.wait()",
  "asyncio.as_completed()", "asyncio.Task", "asyncio.Lock",
  "asyncio.Event", "asyncio.Condition", "asyncio.Semaphore",
  "asyncio.BoundedSemaphore", "asyncio.Queue",
  "asyncio.create_subprocess_exec()" y
  "asyncio.create_subprocess_shell()".

* El paso explícito de objetos corrutina a "asyncio.wait()" está ahora
  obsoleto y será eliminado en Python 3.11. (Contribución de Yury
  Selivanov en bpo-34790.)

* Las siguientes funciones y métodos del módulo "gettext" están
  obsoletos para: "lgettext()", "ldgettext()", "lngettext()" y
  "ldngettext()". Retornan bytes codificados y es posible obtener
  excepciones inesperadas relacionadas con Unicode si hay problemas de
  codificación con las cadenas traducidas. En Python 3 es mucho mejor
  usar alternativas que retornen cadenas Unicode. Estas funciones han
  estado rotas durante mucho tiempo.

  Function "bind_textdomain_codeset()", methods "output_charset()" and
  "set_output_charset()", and the *codeset* parameter of functions
  "translation()" and "install()" are also deprecated, since they are
  only used for the "l*gettext()" functions. (Contributed by Serhiy
  Storchaka in bpo-33710.)

* El método "isAlive()" de la clase "threading.Thread" está ahora
  obsoleto. (Contribución de Dong-hee Na en bpo-35283.)

* Muchas funciones incorporadas y de extensión que toman argumentos
  enteros ahora emitirán una advertencia de deprecación para
  "Decimal"s, "Fraction"s y cualquier otro objeto que se pueda
  convertir a enteros solamente con pérdida (por ejemplo, aquellos que
  tienen el método "__int__()" pero no el método "__index__()"). En
  una versión futura, esto constituirá un error. (Contribución de
  Serhiy Storchaka en bpo-36048.)

* El paso de los siguientes argumentos como argumentos por palabra
  clave está ahora obsoleto:

  * *func* en "functools.partialmethod()", "weakref.finalize()",
    "profile.Profile.runcall()", "cProfile.Profile.runcall()",
    "bdb.Bdb.runcall()", "trace.Trace.runfunc()" y "curses.wrapper()".

  * *function* en "unittest.TestCase.addCleanup()".

  * *fn* en el método "submit()" de las clases
    "concurrent.futures.ThreadPoolExecutor" y
    "concurrent.futures.ProcessPoolExecutor".

  * *callback* en "contextlib.ExitStack.callback()",
    "contextlib.AsyncExitStack.callback()" y
    "contextlib.AsyncExitStack.push_async_callback()".

  * *c* y *typeid* en el método "create()" de las clases
    "multiprocessing.managers.Server" y
    "multiprocessing.managers.SharedMemoryServer".

  * *obj* en "weakref.finalize()".

  En futuros lanzamientos de Python, todos ellos serán argumentos solo
  posicionales. (Contribución de Serhiy Storchaka en bpo-36492.)


APIs y características eliminadas
=================================

Las siguientes características y APIs se han eliminado de Python 3.8:

* A partir de Python 3.3, la importación de ABC desde el módulo
  "collections" quedó obsoleta y la importación debe realizarse desde
  el módulo "collections.abc". La posibilidad de importar desde
  collections se marcó para su eliminación en Python 3.8, pero se ha
  retrasado a Python 3.9. (Consultar bpo-36952.)

* El módulo "macpath", obsoleto desde Python 3.7, ha sido eliminado.
  (Contribución de Victor Stinner en bpo-35471.)

* La función "platform.popen()" ha sido eliminada, después de haber
  estado obsoleta desde Python 3.3: usa "os.popen()" en su lugar.
  (Contribución de Victor Stinner en bpo-35345.)

* La función "time.clock()" ha sido eliminada, después de haber
  quedado obsoleta desde Python 3.3: usa "time.perf_counter()" o
  "time.process_time()" en su lugar, dependiendo de tus requisitos,
  para tener un comportamiento bien definido. (Contribución de
  Matthias Bussonnier en bpo-36895.)

* El script "pyvenv" se ha eliminado, en favor de "python3.8 -m venv",
  para ayudar a eliminar la confusión sobre a qué intérprete de Python
  está vinculado el script "pyvenv". (Contribución de Brett Cannon en
  bpo-25427.)

* Las funciones "parse_qs", "parse_qsl" y "escape" se han eliminado
  del módulo "cgi". Estaban obsoletas desde Python 3.2 o versiones
  anteriores. En su lugar, deberían ser importadas desde los módulos
  "urllib.parse" y "html".

* La función "filemode" se ha eliminado del módulo "tarfile". Estaba
  indocumentada y obsoleta desde Python 3.3.

* El constructor de "XMLParser" ya no acepta el argumento *html*.
  Nunca tuvo efecto y quedó obsoleto en Python 3.4. Todos los demás
  parámetros son ahora parámetros solo nombrados. (Contribución de
  Serhiy Storchaka en bpo-29209.)

* Se ha eliminado el método "doctype()" de "XMLParser". (Contribución
  de Serhiy Storchaka en bpo-29209.)

* Se ha elimina el códec "unicode_internal". (Contribución de Inada
  Naoki en bpo-36297.)

* Los objetos "Cache" y "Statement" del módulo "sqlite3" no estarán
  expuestos al usuario a partir de ahora. (Contribución de Aviv
  Palivoda en bpo-30262.)

* El argumento por palabra clave "bufsize" de "fileinput.input()" y
  "fileinput.FileInput()", marcado como obsoleto e ignorado desde
  Python 3.6, ha sido eliminado. bpo-36952 (Contribución de Matthias
  Bussonnier.)

* Las funciones "sys.set_coroutine_wrapper()" y
  "sys.get_coroutine_wrapper()", obsoletas desde Python 3.7, han sido
  eliminadas; bpo-36933 (Contribución de Matthias Bussonnier.)


Portando a Python 3.8
=====================

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


Cambios en el comportamiento de Python
--------------------------------------

* Las expresiones yield (tanto la cláusula "yield" como la cláusula
  "yield from") ahora no están permitidas en comprensiones y
  expresiones generadoras (excepto en la expresión iterable en la
  cláusula "for" situada más a la izquierda). (Contribución de Serhiy
  Storchaka en bpo-10544.)

* El compilador ahora produce una advertencia "SyntaxWarning" cuando
  se utilizan comprobaciones de identidad ("is" e "is not") con
  ciertos tipos de literales (por ejemplo, cadenas, números). A
  menudo, estas pueden funcionar accidentalmente en CPython, pero no
  está garantizado por las especificaciones del lenguaje. La
  advertencia advierte a los usuarios que utilicen pruebas de igualdad
  ("==" y "!=") en su lugar. (Contribución de Serhiy Storchaka en
  bpo-34850.)

* El intérprete de CPython puede tolerar excepciones en algunas
  circunstancias. En Python 3.8 esto sucederá con menos frecuencia. En
  particular, las excepciones que se generan al obtener atributos del
  diccionario de tipos ya no son ignoradas. (Contribución de Serhiy
  Storchaka en bpo-35459.)

* Se ha eliminado las implementaciones de "__str__" para los tipos
  incorporados "bool", "int", "float", "complex" y algunas clases de
  la biblioteca estándar. Ahora heredan el método "__str__()" de
  "object". Como resultado, definir el método "__repr__()" en una
  subclase de estas clases afectará a su representación como cadena de
  caracteres. (Contribución de Serhiy Storchaka en bpo-36793.)

* En AIX, el atributo "sys.platform" ya no contiene la versión
  principal. Es decir, siempre es "'aix'", en lugar de "'aix3'" ..
  "'aix7'". Dado que las versiones anteriores de Python incluyen el
  número de versión, se recomienda usar siempre
  "sys.platform.startswith('aix')". (Contribución de M. Felt en
  bpo-36588.)

* "PyEval_AcquireLock()" y "PyEval_AcquireThread()" ahora terminan el
  hilo actual si se llaman mientras el intérprete está finalizando,
  haciéndolos consistentes con "PyEval_RestoreThread()",
  "Py_END_ALLOW_THREADS()" y "PyGILState_Ensure()". Si no se desea
  este comportamiento, se tiene que proteger la invocación comprobando
  "_Py_IsFinalizing()" o "sys.is_finalizing()". (Contribución de
  Joannah Nanjekye en bpo-36475.)


Cambios en la API de Python
---------------------------

* La función "os.getcwdb()" ahora usa la codificación UTF-8 en
  Windows, en lugar de la página de códigos ANSI: consultar **PEP
  529** para el fundamento. La función ya no está obsoleta en Windows.
  (Contribución de Victor Stinner en bpo-37412.)

* "subprocess.Popen" ahora puede usar "os.posix_spawn()" en algunos
  casos para un mejor rendimiento. En el Subsistema de Windows para
  Linux y en la Emulación de usuario QEMU, el constructor "Popen" que
  usa "os.posix_spawn()" ya no genera una excepción como "missing
  program" ante errores. En cambio, el proceso hijo falla con un valor
  "returncode" distinto de cero. (Contribución de Joannah Nanjekye y
  Victor Stinner en bpo-35537.)

* El argumento *preexec_fn* de "subprocess.Popen" ya no es compatible
  con subintérpretes. El uso del parámetro en un subintérprete ahora
  lanza una excepción "RuntimeError". (Contribución de Eric Snow en
  bpo-34651, modificado por Christian Heimes en bpo-37951.)

* El método "imap.IMAP4.logout()" ya no ignora silenciosamente
  excepciones arbitrarias. (Contribución de Victor Stinner en
  bpo-36348.)

* La función "platform.popen()" ha sido eliminada, después de haber
  estado obsoleta desde Python 3.3: usa "os.popen()" en su lugar.
  (Contribución de Victor Stinner en bpo-35345.)

* La función "statistics.mode()" ya no lanza una excepción cuando se
  proporcionan datos multimodales. Ahora, en cambio, retorna la
  primera moda encontrada en los datos de entrada. (Contribución de
  Raymond Hettinger en bpo-35892.)

* El método "selection()" de la clase "tkinter.ttk.Treeview" ya no
  acepta argumentos. Usarlo con argumentos para cambiar la selección
  quedó obsoleto en Python 3.6. Utiliza métodos especializados, como
  "selection_set()", para cambiar la selección. (Contribución de
  Serhiy Storchaka en bpo-31508.)

* Los métodos "writexml()", "toxml()" y "toprettyxml()" de
  "xml.dom.minidom" y el método "write()" de "xml.etree", ahora
  conservan el orden de los atributos especificado por el usuario.
  (Contribución de Diego Rojas y Raymond Hettinger en bpo-34160.)

* Una base de datos "dbm.dumb" abierta con el flag "'r'" ahora es de
  solo lectura. "dbm.dumb.open()" con los flags "'r'" y "'w'" ya no
  crea una base de datos si no existe. (Contribución de Serhiy
  Storchaka en bpo-32749.)

* El método "doctype()" definido en una subclase de "XMLParser" ya no
  será invocado y emitirá una advertencia "RuntimeWarning" en lugar de
  "DeprecationWarning". Define el método "doctype()" en un objetivo
  para manejar una declaración doctype de XML. (Contribución de Serhiy
  Storchaka en bpo-29209.)

* Ahora se lanza una excepción "RuntimeError" cuando la metaclase
  personalizada no proporciona la entrada "__classcell__" en el
  espacio de nombres pasado a "type.__new__". En Python 3.6--3.7. se
  emitía una advertencia "DeprecationWarning" (Contribución de Serhiy
  Storchaka en bpo-23722.)

* La clase "cProfile.Profile" ahora se puede usar como gestor de
  contexto. (Contribución de Scott Sanderson en bpo-29235.)

* "shutil.copyfile()", "shutil.copy()", "shutil.copy2()",
  "shutil.copytree()" y "shutil.move()" usan llamadas al sistema de
  "copia-rápida" específicas de la plataforma. (Consultar la sección
  Operaciones de copia eficientes dependientes de la plataforma).

* El tamaño predeterminado del búfer de "shutil.copyfile()" en Windows
  se ha cambiado de 16 KiB a 1 MiB.

* La estructura "PyGC_Head" ha cambiado por completo. Todo código que
  haga uso de algún miembro de la estructura debe reescribirse.
  (Consultar bpo-33597.)

* La estructura "PyInterpreterState" se ha movido a los archivos de
  cabeceras "internos" (específicamente a
  Include/internal/pycore_pystate.h). Un "PyInterpreterState" opaco
  todavía está disponible como parte de la API pública (y ABI
  estable). La documentación indica que ninguno de los campos de la
  estructura es público, por lo que esperamos que nadie los haya
  estado usando. Sin embargo, si utilizas uno o más de esos campos
  privados y no tienes otra alternativa, abre una issue BPO.
  Trabajaremos para ayudarte a adaptarlo (posiblemente incluyendo
  funciones de acceso a la API pública). (Consultar bpo-35886.)

* El método "mmap.flush()" ahora retorna "None" en caso de éxito y
  lanza una excepción en caso de error, en todas las plataformas.
  Anteriormente, su comportamiento dependía de la plataforma: en
  Windows retornaba un valor distinto de cero en caso de éxito y cero
  ante un error. En Unix se retornaba un valor de cero en caso de
  éxito y se lanzaba una excepción ante un error. (Contribución de
  Berker Peksag en bpo-2122.)

* Los módulos "xml.dom.minidom" y "xml.sax" ya no procesan entidades
  externas de forma predeterminada. (Contribución de Christian Heimes
  en bpo-17239.)

* Eliminar una clave de una base de datos "dbm" de solo lectura
  ("dbm.dumb", "dbm.gnu" o "dbm.ndbm") lanza una excepción "error"
  ("dbm.dumb.error", "dbm.gnu.error" o "dbm.ndbm.error") en lugar de
  "KeyError". (Contribución de Xiang Zhang en bpo-33106.)

* AST simplificado para literales. Todas las constantes se
  representarán como instancias de "ast.Constant". La instanciación de
  las antiguas clases "Num", "Str", "Bytes", "NameConstant" y
  "Ellipsis" retornará ahora una instancia de "Constant".
  (Contribución de Serhiy Storchaka en bpo-32892.)

* "expanduser()" en Windows ahora usa preferentemente la variable de
  entorno "USERPROFILE" y no usa "HOME", que normalmente no está
  establecido para cuentas de usuario normales. (Contribución de
  Anthony Sottile en bpo-36264.)

* The exception "asyncio.CancelledError" now inherits from
  "BaseException" rather than "Exception" and no longer inherits from
  "concurrent.futures.CancelledError". (Contributed by Yury Selivanov
  in bpo-32528.)

* La función "asyncio.wait_for()" ahora espera correctamente la
  cancelación cuando se usa una instancia de "asyncio.Task".
  Anteriormente, al alcanzar *timeout*, se cancelaba y retornaba de
  inmediato. (Contribución de Elvis Pranskevichus en bpo-32751.)

* La función "asyncio.BaseTransport.get_extra_info()" ahora retorna un
  objeto socket seguro cuando se pasa 'socket' al parámetro *name*.
  (Contribución de Yury Selivanov en bpo-37027.)

* "asyncio.BufferedProtocol" ha pasado a formar parte de la API
  estable.

* Las dependencias de DLLs para módulos de extensión y DLLs cargadas
  con "ctypes" en Windows ahora se resuelven de forma más segura. Solo
  las rutas del sistema, el directorio que contiene el archivo DLL o
  PYD y los directorios agregados mediante "add_dll_directory()" se
  buscan para las dependencias en tiempo de carga. Específicamente,
  "PATH" y el directorio de trabajo actual ya no se utilizan, y las
  modificaciones de estos ya no tendrán ningún efecto en la resolución
  normal de la DLL. Si tu aplicación se basa en estos mecanismos,
  debes buscar "add_dll_directory()" y, si existe, utilizarlo para
  agregar tu directorio DLL mientras carga tu biblioteca. Ten en
  cuenta que los usuarios de Windows 7 deberán asegurarse de que se
  haya instalado Windows Update KB2533623 (esto también lo verifica el
  instalador). (Contribución de Steve Dower en bpo-36085.)

* Los archivos de cabeceras y las funciones relacionadas con pgen se
  han eliminado después de su reemplazo por una implementación pura de
  Python. (Contribución de Pablo Galindo en bpo-36623.)

* "types.CodeType" tiene un nuevo parámetro en la segunda posición del
  constructor (*posonlyargcount*) para admitir argumentos solo
  posicionales, definidos en **PEP 570**. El primer argumento
  (*argcount*) ahora representa el número total de argumentos
  posicionales (incluidos los argumentos solo posicionales). El nuevo
  método "replace()" de "types.CodeType" se puede utilizar para hacer
  que el código esté preparado para el futuro.

* The parameter "digestmod" for "hmac.new()" no longer uses the MD5
  digest by default.


Cambios en la API de C
----------------------

* La estructura "PyCompilerFlags" tiene un nuevo campo
  *cf_feature_version*. Debe inicializarse en "PY_MINOR_VERSION". El
  campo se ignora de forma predeterminada y se usa, si y solo si, el
  flag "PyCF_ONLY_AST" está establecido en *cf_flags*. (Contribución
  de Guido van Rossum en bpo-35766.)

* La función "PyEval_ReInitThreads()" se ha eliminado de la API de C.
  No debe llamarse explícitamente: usa "PyOS_AfterFork_Child()" en su
  lugar. (Contribución de Victor Stinner en bpo-36728.)

* En Unix, las extensiones de C ya no están vinculadas a libpython,
  excepto en Android y Cygwin. Cuando Python está integrado,
  "libpython" no debe cargarse con "RTLD_LOCAL", sino con
  "RTLD_GLOBAL" en su lugar. Anteriormente, no era posible usar
  "RTLD_LOCAL" para cargar extensiones de C que no estuvieran
  vinculadas a "libpython", como las extensiones de C de la biblioteca
  estándar construida por la sección "*shared*" de "Modules/Setup".
  (Contribución de Victor Stinner en bpo-21536.)

* El uso de variantes de formato "#" en el análisis o la construcción
  de valores (por ejemplo: "PyArg_ParseTuple()", "Py_BuildValue()",
  "PyObject_CallFunction()", etc.) sin "PY_SSIZE_T_CLEAN" definido
  ahora lanza una advertencia "DeprecationWarning". Se eliminará en
  Python 3.10 ó 4.0. Consultar Analizando argumentos y construyendo
  valores para más detalles. (Contribución de Inada Naoki en
  bpo-36381.)

* Las instancias de tipos asignados al montón (como los creados con
  "PyType_FromSpec()") contienen una referencia a su objeto de tipo.
  El aumento del recuento de referencias de estos objetos de tipo se
  ha movido de "PyType_GenericAlloc()" a las funciones de más bajo
  nivel, "PyObject_Init()" y "PyObject_INIT()". Esto hace que los
  tipos creados mediante "PyType_FromSpec()" se comporten como otras
  clases en el código gestionado.

  Los tipos asignados estáticamente no se ven afectados.

  Para la gran mayoría de casos, no debería haber efectos secundarios.
  Sin embargo, los tipos que aumentan manualmente el recuento de
  referencias después de asignar una instancia (quizás para evitar el
  error) ahora pueden volverse inmortales. Para evitar esto, estas
  clases deben llamar a Py_DECREF en el objeto de tipo durante la
  desasignación de la instancia.

  Para portar correctamente estos tipos a Python 3.8, aplica los
  siguientes cambios:

  * Elimina "Py_INCREF" en el objeto de tipo después de asignar una
    instancia, si la hubiera. Esto puede suceder después de invocar a
    "PyObject_New()", "PyObject_NewVar()", "PyObject_GC_New()",
    "PyObject_GC_NewVar()", o cualquier otro asignador personalizado
    que use "PyObject_Init()" o "PyObject_INIT()".

    Ejemplo:

       static foo_struct *
       foo_new(PyObject *type) {
           foo_struct *foo = PyObject_GC_New(foo_struct, (PyTypeObject *) type);
           if (foo == NULL)
               return NULL;
       #if PY_VERSION_HEX < 0x03080000
           // Workaround for Python issue 35810; no longer necessary in Python 3.8
           PY_INCREF(type)
       #endif
           return foo;
       }

  * Asegúrate de que todas las funciones personalizadas "tp_dealloc"
    de los tipos asignados al montón disminuyan el recuento de
    referencias del tipo.

    Ejemplo:

       static void
       foo_dealloc(foo_struct *instance) {
           PyObject *type = Py_TYPE(instance);
           PyObject_GC_Del(instance);
       #if PY_VERSION_HEX >= 0x03080000
           // This was not needed before Python 3.8 (Python issue 35810)
           Py_DECREF(type);
       #endif
       }

  (Contribución de Eddie Elizondo en bpo-35810.)

* La macro "Py_DEPRECATED()" ha sido implementada para MSVC. La macro
  ahora debe ser colocada antes del nombre del símbolo.

  Ejemplo:

     Py_DEPRECATED(3.8) PyAPI_FUNC(int) Py_OldFunction(void);

  (Contribución de Zackery Spytz en bpo-33407.)

* El intérprete ya no pretende dar suporte nunca más a la
  compatibilidad binaria de tipos de extensión entre versiones de
  características. Un "PyTypeObject" exportado por un módulo de
  extensión de terceros se supone que tiene todas las ranuras
  esperadas por la versión actual de Python, incluyendo "tp_finalize"
  ("Py_TPFLAGS_HAVE_FINALIZE" ya no se verifica antes de leer
  "tp_finalize").

  (Contribución de Antoine Pitrou en bpo-32388.)

* Las funciones "PyNode_AddChild()" y "PyParser_AddToken()" ahora
  aceptan dos argumentos "int" adicionales, *end_lineno* y
  *end_col_offset*.

* El archivo "libpython38.a" ya no se incluye en la distribución
  normal de Windows. Si se necesita este archivo, se puede generar con
  las herramientas "gendef" y "dlltool", que son parte del paquete
  binutils de MinGW:

     gendef - python38.dll > tmp.def
     dlltool --dllname python38.dll --def tmp.def --output-lib libpython38.a

  La ubicación de un archivo "pythonXY.dll" instalado dependerá de las
  opciones de instalación y de la versión y el idioma de Windows.
  Consultar Uso de Python en Windows para obtener más información. La
  biblioteca resultante debe colocarse en el mismo directorio que
  "pythonXY.lib", que generalmente es el directorio "libs" en tu
  instalación de Python.

  (Contribución de Steve Dower en bpo-37351.)


Cambios en el bytecode de CPython
---------------------------------

* El bucle del intérprete se ha simplificado moviendo al compilador la
  lógica para el desenredo de la pila de bloques. El compilador ahora
  emite instrucciones explícitas para ajustar la pila de valores y
  llamar al código de limpieza para "break", "continue" y "return".

  Eliminados los códigos de operación "BREAK_LOOP", "CONTINUE_LOOP",
  "SETUP_LOOP" y "SETUP_EXCEPT". Agregados los nuevos códigos de
  operación "ROT_FOUR", "BEGIN_FINALLY", "CALL_FINALLY" y
  "POP_FINALLY". Modificados los códigos de operación "END_FINALLY" y
  "WITH_CLEANUP_START".

  (Contribución de Mark Shannon, Antoine Pitrou y Serhiy Storchaka en
  bpo-17611.)

* Agregado el código de operación "END_ASYNC_FOR" para manejar
  excepciones lanzadas mientras se espera al siguiente elemento en un
  ciclo "async for". (Contribución de Serhiy Storchaka en bpo-33041.)

* El código de operación "MAP_ADD" ahora espera el valor como primer
  elemento de la pila y la clave como segundo elemento. Este cambio se
  realizó para que la clave siempre se evalúe antes que el valor en
  los diccionarios por compresión, como se propone en **PEP 572**.
  (Contribución de Jörn Heissler en bpo-35224.)


Demos y herramientas
--------------------

Se ha añadido un script de evaluación de rendimiento para cronometrar
varias formas de acceder a variables:
"Tools/scripts/var_access_benchmark.py". (Contribución de Raymond
Hettinger en bpo-35884.)

A continuación, se muestra un resumen de las mejoras de rendimiento
desde Python 3.3:

   Python version                       3.3     3.4     3.5     3.6     3.7     3.8
   --------------                       ---     ---     ---     ---     ---     ---

   Variable and attribute read access:
       read_local                       4.0     7.1     7.1     5.4     5.1     3.9
       read_nonlocal                    5.3     7.1     8.1     5.8     5.4     4.4
       read_global                     13.3    15.5    19.0    14.3    13.6     7.6
       read_builtin                    20.0    21.1    21.6    18.5    19.0     7.5
       read_classvar_from_class        20.5    25.6    26.5    20.7    19.5    18.4
       read_classvar_from_instance     18.5    22.8    23.5    18.8    17.1    16.4
       read_instancevar                26.8    32.4    33.1    28.0    26.3    25.4
       read_instancevar_slots          23.7    27.8    31.3    20.8    20.8    20.2
       read_namedtuple                 68.5    73.8    57.5    45.0    46.8    18.4
       read_boundmethod                29.8    37.6    37.9    29.6    26.9    27.7

   Variable and attribute write access:
       write_local                      4.6     8.7     9.3     5.5     5.3     4.3
       write_nonlocal                   7.3    10.5    11.1     5.6     5.5     4.7
       write_global                    15.9    19.7    21.2    18.0    18.0    15.8
       write_classvar                  81.9    92.9    96.0   104.6   102.1    39.2
       write_instancevar               36.4    44.6    45.8    40.0    38.9    35.5
       write_instancevar_slots         28.7    35.6    36.1    27.3    26.6    25.7

   Data structure read access:
       read_list                       19.2    24.2    24.5    20.8    20.8    19.0
       read_deque                      19.9    24.7    25.5    20.2    20.6    19.8
       read_dict                       19.7    24.3    25.7    22.3    23.0    21.0
       read_strdict                    17.9    22.6    24.3    19.5    21.2    18.9

   Data structure write access:
       write_list                      21.2    27.1    28.5    22.5    21.6    20.0
       write_deque                     23.8    28.7    30.1    22.7    21.8    23.5
       write_dict                      25.9    31.4    33.3    29.3    29.2    24.7
       write_strdict                   22.9    28.4    29.9    27.5    25.2    23.1

   Stack (or queue) operations:
       list_append_pop                144.2    93.4   112.7    75.4    74.2    50.8
       deque_append_pop                30.4    43.5    57.0    49.4    49.2    42.5
       deque_append_popleft            30.8    43.7    57.3    49.7    49.7    42.8

   Timing loop:
       loop_overhead                    0.3     0.5     0.6     0.4     0.3     0.3

Las evaluaciones de rendimiento se realizaron en un procesador Intel®
Core™ i7-4960HQ ejecutando las compilaciones de 64-bits para macOS
disponibles en python.org. El script de evaluación de rendimiento
muestra los tiempos en nanosegundos.


Cambios notables en Python 3.8.1
================================

Debido a importantes preocupaciones de seguridad, el parámetro
*reuse_address* de "asyncio.loop.create_datagram_endpoint()" ya no
está soportado. Esto se debe al comportamiento de la opción
"SO_REUSEADDR" del socket en UDP. Para obtener más detalles, consulta
la documentación de "loop.create_datagram_endpoint()". (Contribución
de Kyle Stanley, Antoine Pitrou y Yury Selivanov en bpo-37228.)


Cambios notables en Python 3.8.2
================================

Se ha corregido una regresión con la retrollamada "ignore" de
"shutil.copytree()". Los tipos de los argumentos ahora son str y
List[str] nuevamente. (Contribución de Manuel Barkhau y Giampaolo
Rodola en bpo-39390.)


Cambios notables en Python 3.8.3
================================

Se han actualizado los valores constantes de los flags futuros del
módulo "__future__" para evitar colisiones con los flags del
compilador. Anteriormente, "PyCF_ALLOW_TOP_LEVEL_AWAIT" estaba en
conflicto con "CO_FUTURE_DIVISION". (Contribución de Batuhan Taskaya
en bpo-39562.)


Notable changes in Python 3.8.8
===============================

Earlier Python versions allowed using both ";" and "&" as query
parameter separators in "urllib.parse.parse_qs()" and
"urllib.parse.parse_qsl()".  Due to security concerns, and to conform
with newer W3C recommendations, this has been changed to allow only a
single separator key, with "&" as the default.  This change also
affects "cgi.parse()" and "cgi.parse_multipart()" as they use the
affected functions internally. For more details, please see their
respective documentation. (Contributed by Adam Goldschmidt, Senthil
Kumaran and Ken Jin in bpo-42967.)


Notable changes in Python 3.8.9
===============================

A security fix alters the "ftplib.FTP" behavior to not trust the IPv4
address sent from the remote server when setting up a passive data
channel.  We reuse the ftp server IP address instead.  For unusual
code requiring the old behavior, set a
"trust_server_pasv_ipv4_address" attribute on your FTP instance to
"True".  (See bpo-43285)


Notable changes in Python 3.8.10
================================


macOS 11.0 (Big Sur) and Apple Silicon Mac support
--------------------------------------------------

As of 3.8.10, Python now supports building and running on macOS 11
(Big Sur) and on Apple Silicon Macs (based on the "ARM64"
architecture). A new universal build variant, "universal2", is now
available to natively support both "ARM64" and "Intel 64" in one set
of executables. Note that support for "weaklinking", building binaries
targeted for newer versions of macOS that will also run correctly on
older versions by testing at runtime for missing features, is not
included in this backport from Python 3.9; to support a range of macOS
versions, continue to target for and build on the oldest version in
the range.

(Originally contributed by Ronald Oussoren and Lawrence D'Anna in
bpo-41100, with fixes by FX Coudert and Eli Rykoff, and backported to
3.8 by Maxime Bélanger and Ned Deily)


Notable changes in Python 3.8.10
================================


urllib.parse
------------

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 bpo-43882)


Notable changes in Python 3.8.12
================================


Cambios en la API de Python
---------------------------

Starting with Python 3.8.12 the "ipaddress" module no longer accepts
any leading zeros in IPv4 address strings. Leading zeros are ambiguous
and interpreted as octal notation by some libraries. For example the
legacy function "socket.inet_aton()" treats leading zeros as octal
notation. glibc implementation of modern "inet_pton()" does not accept
any leading zeros.

(Originally contributed by Christian Heimes in bpo-36384, and
backported to 3.8 by Achraf Merzouki)


Notable security feature in 3.8.14
==================================

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 Changes in 3.8.17
=========================


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**.)


Notable changes in 3.8.20
=========================


ipaddress
---------

* Fixed "is_global" and "is_private" behavior in "IPv4Address",
  "IPv6Address", "IPv4Network" and "IPv6Network".


email
-----

* Headers with embedded newlines are now quoted on output.

  The "generator" will now refuse to serialize (write) headers that
  are improperly folded or delimited, such that they would be parsed
  as multiple headers or joined with adjacent data. If you need to
  turn this safety feature off, set "verify_generated_headers".
  (Contributed by Bas Bloemsaat and Petr Viktorin in gh-121650.)

* "email.utils.getaddresses()" and "email.utils.parseaddr()" now
  return "('', '')" 2-tuples in more situations where invalid email
  addresses are encountered, instead of potentially inaccurate values.
  An optional *strict* parameter was added to these two functions: use
  "strict=False" to get the old behavior, accepting malformed inputs.
  "getattr(email.utils, 'supports_strict_parsing', False)" can be used
  to check if the *strict* paramater is available. (Contributed by
  Thomas Dwyer and Victor Stinner for gh-102988 to improve the
  CVE-2023-27043 fix.)
