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. Python 3.8 se lanzó el 14 de octubre de 2019. Para obtener detalles completos, consulte changelog.
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¶
There is a new function parameter syntax /
to indicate that some
function parameters must be specified positionally and cannot be used as
keyword arguments. This is the same notation shown by help()
for C
functions annotated with Larry Hastings”
Argument Clinic tool.
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 versiones y debug builds ahora son compatibles con ABI: definir la macro Py_DEBUG
ya no implica la macro Py_TRACE_REFS
, que presenta la única incompatibilidad ABI. La macro Py_TRACE_REFS
, que agrega la función sys.getobjects()
y la variable de entorno PYTHONDUMPREFS
, se puede configurar utilizando la nueva opción de compilación ./configure --with-trace-refs
. (Contribuido por 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-strings. 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:
Nuevas funciones:
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.)
PEP 590: Vectorcall: un protocolo de llamada rápida para CPython¶
El protocolo vectorcall se agrega a la API de Python / C. Está destinado a formalizar las optimizaciones existentes que ya se realizaron para varias clases. Cualquier static type 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, Mark Shannon y Petr Viktorin 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áusulafinally
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
yfractions.Fraction
ahora tienen un métodoas_integer_ratio()
como el que se encuentra enfloat
ydecimal.Decimal
. Esta extensión menor de la API hace posible escribirnumerator, 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
ycomplex
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}
enexpresiones 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
yreturn
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 maggie') ('SIMPSONS', 'homer', 'marge', 'bart', 'lisa', 'maggie')
(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 unSyntaxWarning
con una sugerencia útil. Esto representa una mejora con respecto a la implementación previa en la que solo se mostraba unTypeError
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
odatetime.datetime
ydatetime.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 dedatetime.timedelta
, comoastimezone()
. (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étodoreplace()
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 como4258𝑥 ≡ 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 aasync
yawait
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.)
La excepción asyncio.CancelledError
ahora hereda de BaseException
en lugar de Exception
y ya no hereda de concurrent.futures.CancelledError
. (Contribuido por Yury Selivanov en 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¶
Added new alternate constructors datetime.date.fromisocalendar()
and
datetime.datetime.fromisocalendar()
, which construct date
and
datetime
objects respectively from ISO year, week number, and weekday;
these are the inverse of each class’s isocalendar
method.
(Contributed by Paul Ganssle in 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.)
Nuevo en 3.8.1:
Agregue la opción para desactivar el parpadeo del cursor. (Contribuido por Zackery Spytz en bpo-4603.)
La tecla Escape ahora cierra las ventanas de finalización IDLE. (Contribuido por Johnny Najera en bpo-38944.)
Los cambios anteriores se han portado a las versiones de mantenimiento de Python 3.7.
Agrega palabras clave a la lista de finalización del nombre del módulo. (Contribución de Terry J. Reedy en 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 debug build, el finalizador io.IOBase
ahora registra la excepción si falla el método close()
. La excepción se ignora de forma silenciosa de forma predeterminada en la versión de la versión. (Contribuido por 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¶
Added a force keyword argument to logging.basicConfig()
.
When set to true, any existing handlers attached
to the root logger are removed and closed before carrying out the
configuration specified by the other arguments.
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.)
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¶
pathlib.Path
methods that return a boolean result like
exists()
, is_dir()
,
is_file()
, is_mount()
,
is_symlink()
, is_block_device()
,
is_char_device()
, is_fifo()
,
is_socket()
now return False
instead of raising
ValueError
or its subclass UnicodeEncodeError
for paths that
contain characters unrepresentable at the OS level.
(Contributed by Serhiy Storchaka in bpo-33721.)
Added pathlib.Path.link_to()
which creates a hard link pointing
to a path.
(Contributed by Joannah Nanjekye in bpo-26978)
Note that link_to
was deprecated in 3.10 and removed in 3.12 in
favor of a hardlink_to
method added in 3.10 which matches the
semantics of the existing symlink_to
method.
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¶
Added create_server()
and has_dualstack_ipv6()
convenience functions to automate the necessary tasks usually involved when
creating a server socket, including accepting both IPv4 and IPv6 connections
on the same socket. (Contributed by Giampaolo Rodolà in bpo-17561.)
The socket.if_nameindex()
, socket.if_nametoindex()
, and
socket.if_indextoname()
functions have been implemented on Windows.
(Contributed by Zackery Spytz in 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¶
Added statistics.fmean()
as a faster, floating-point variant of
statistics.mean()
. (Contributed by Raymond Hettinger and
Steven D’Aprano in bpo-35904.)
Added statistics.geometric_mean()
(Contributed by Raymond Hettinger in 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 lanza 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.)
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
ytyping.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
ytyping.runtime_checkable()
. ABCs simples comotyping.SupportsInt
ahora son subclases deProtocol
.Nueva clase protocolo
typing.SupportsIndex
.Nuevas funciones
typing.get_origin()
ytyping.get_args()
.
unicodedata¶
El módulo unicodedata
se ha actualizado para usar la versión 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).
Added addModuleCleanup()
and
addClassCleanup()
to unittest to support
cleanups for setUpModule()
and
setUpClass()
.
(Contributed by Lisa Roach in 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.)
The xml.etree.ElementTree
module provides a new function
–xml.etree.ElementTree.canonicalize()
that implements C14N 2.0.
(Contributed by Stefan Behnel in 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ónos.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()
yshutil.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 deshutil.copyfileobj()
basada enmemoryview()
. 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ónos.scandir()
y todas las funciones de copia que dependen de ella usan el valor en caché deos.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 deos.stat()
se reduce en un 38%, lo que hace queshutil.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.Se eliminó un miembro
Py_ssize_t
dePyGC_Head
. El tamaño de todos los objetos rastreados de GC (por ejemplo, tupla, lista, dict) se reduce en 4 u 8 bytes. (Aportado por 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 flagm
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 programapython3.8m
se ha eliminado.Solo el script
python3.8-config
es instalado, el scriptpython3.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 pormake 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:
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()
yPyByteArray_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 tipoconst char *
en vez dechar *
. (Contribución de Serhiy Storchaka en bpo-33818.)La dualidad conformada por
Modules/Setup.dist
yModules/Setup
ha sido eliminada. Anteriormente, al actualizar el árbol de fuentes de CPython, se tenía que copiar manualmenteModules/Setup.dist
(dentro del árbol de fuentes) aModules/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 comoPyArg_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__()
(comoDecimal
yFraction
).PyNumber_Check()
ahora retornará1
para los objetos que implementen__index__()
.PyNumber_Long()
,PyNumber_Float()
yPyFloat_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 paralelaPyObject_INIT
) en lugar de enPyType_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.)The new function
PyCode_NewWithPosOnlyArgs()
allows to create code objects likePyCode_New()
, but with an extra posonlyargcount parameter for indicating the number of positional-only arguments. (Contributed by Pablo Galindo in bpo-37221.)Py_SetPath()
ahora establecesys.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, usarbdist_wheel
(paquetes wheel) en su lugar. (Contribución de Victor Stinner en bpo-37481.)Los métodos
getchildren()
ygetiterator()
del móduloElementTree
ahora emiten una advertenciaDeprecationWarning
, en lugar dePendingDeprecationWarning
. 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 deconcurrent.futures.ThreadPoolExecutor
está obsoleto y será prohibido en Python 3.9. (Contribución de Elvis Pranskevichus en bpo-34075.)The
__getitem__()
methods ofxml.dom.pulldom.DOMEventStream
,wsgiref.util.FileWrapper
andfileinput.FileInput
have been deprecated.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 clasetyping.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
yEllipsis
del móduloast
están consideradas obsoletas y serán eliminadas en versiones futuras de Python. La claseConstant
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()
yvisit_Ellipsis()
de la claseast.NodeVisitor
están obsoletos ahora y serán invocados en versiones futuras de Python. Agregar el métodovisit_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 usarasync 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()
yasyncio.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()
yldngettext()
. 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.Función
bind_textdomain_codeset()
, métodosoutput_charset()
yset_output_charset()
, y el parámetro codeset de las funcionestranslation()
yinstall()
también están en desuso, ya que solo se usan para las funcionesl*gettext()
. (Contribución de Serhiy Storchaka en bpo-33710.)The
isAlive()
method ofthreading.Thread
has been deprecated. (Contributed by Donghee Na in 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()
ycurses.wrapper()
.function en
unittest.TestCase.addCleanup()
.fn en el método
submit()
de las clasesconcurrent.futures.ThreadPoolExecutor
yconcurrent.futures.ProcessPoolExecutor
.callback en
contextlib.ExitStack.callback()
,contextlib.AsyncExitStack.callback()
ycontextlib.AsyncExitStack.push_async_callback()
.c y typeid en el método
create()
de las clasesmultiprocessing.managers.Server
ymultiprocessing.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:
Starting with Python 3.3, importing ABCs from
collections
was deprecated, and importing should be done fromcollections.abc
. Being able to import from collections was marked for removal in 3.8, but has been delayed to 3.9. (See gh-81134.)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: usaos.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: usatime.perf_counter()
otime.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 depython3.8 -m venv
, para ayudar a eliminar la confusión sobre a qué intérprete de Python está vinculado el scriptpyvenv
. (Contribución de Brett Cannon en bpo-25427.)Las funciones
parse_qs
,parse_qsl
yescape
se han eliminado del módulocgi
. Estaban obsoletas desde Python 3.2 o versiones anteriores. En su lugar, deberían ser importadas desde los módulosurllib.parse
yhtml
.La función
filemode
se ha eliminado del módulotarfile
. 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()
deXMLParser
. (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
yStatement
del módulosqlite3
no estarán expuestos al usuario a partir de ahora. (Contribución de Aviv Palivoda en bpo-30262.)El argumento por palabra clave
bufsize
defileinput.input()
yfileinput.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()
ysys.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áusulayield from
) ahora no están permitidas en comprensiones y expresiones generadoras (excepto en la expresión iterable en la cláusulafor
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
eis 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 incorporadosbool
,int
,float
,complex
y algunas clases de la biblioteca estándar. Ahora heredan el método__str__()
deobject
. 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 siempresys.platform.startswith('aix')
. (Contribución de M. Felt en bpo-36588.)PyEval_AcquireLock()
yPyEval_AcquireThread()
ahora terminan el hilo actual si se llaman mientras el intérprete está finalizando, haciéndolos consistentes conPyEval_RestoreThread()
,Py_END_ALLOW_THREADS()
yPyGILState_Ensure()
. Si no se desea este comportamiento, se tiene que proteger la invocación comprobando_Py_IsFinalizing()
osys.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 usaros.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 constructorPopen
que usaos.posix_spawn()
ya no lanza una excepción como «missing program» ante errores. En cambio, el proceso hijo falla con un valorreturncode
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ónRuntimeError
. (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: usaos.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 clasetkinter.ttk.Treeview
ya no acepta argumentos. Usarlo con argumentos para cambiar la selección quedó obsoleto en Python 3.6. Utiliza métodos especializados, comoselection_set()
, para cambiar la selección. (Contribución de Serhiy Storchaka en bpo-31508.)Los métodos
writexml()
,toxml()
ytoprettyxml()
dexml.dom.minidom
y el métodowrite()
dexml.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 deXMLParser
ya no será invocado y emitirá una advertenciaRuntimeWarning
en lugar deDeprecationWarning
. Define el métododoctype()
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 atype.__new__
. En Python 3.6–3.7. se emitía una advertenciaDeprecationWarning
(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()
yshutil.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). UnPyInterpreterState
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 retornaNone
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
yxml.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
odbm.ndbm
) lanza una excepciónerror
(dbm.dumb.error
,dbm.gnu.error
odbm.ndbm.error
) en lugar deKeyError
. (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 clasesNum
,Str
,Bytes
,NameConstant
yEllipsis
retornará ahora una instancia deConstant
. (Contribución de Serhiy Storchaka en bpo-32892.)expanduser()
en Windows ahora usa preferentemente la variable de entornoUSERPROFILE
y no usaHOME
, que normalmente no está establecido para cuentas de usuario normales. (Contribución de Anthony Sottile en bpo-36264.)La excepción
asyncio.CancelledError
ahora hereda deBaseException
en lugar deException
y ya no hereda deconcurrent.futures.CancelledError
. (Contribuido por Yury Selivanov en bpo-32528.)La función
asyncio.wait_for()
ahora espera correctamente la cancelación cuando se usa una instancia deasyncio.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 medianteadd_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 buscaradd_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étodoreplace()
detypes.CodeType
se puede utilizar para hacer que el código esté preparado para el futuro.El parámetro
digestmod
dehmac.new()
ya no usa el resumen MD5 por defecto.
Cambios en la API de C¶
La estructura
PyCompilerFlags
obtuvo un nuevo campo cf_feature_version. Debe inicializarse enPY_MINOR_VERSION
. El campo se ignora de forma predeterminada y se usa solo si el indicadorPyCF_ONLY_AST
está establecido en cf_flags. (Aportado por Guido van Rossum en bpo-35766.)La función
PyEval_ReInitThreads()
se ha eliminado de la API de C. No debe llamarse explícitamente: usaPyOS_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 conRTLD_LOCAL
, sino conRTLD_GLOBAL
en su lugar. Anteriormente, no era posible usarRTLD_LOCAL
para cargar extensiones de C que no estuvieran vinculadas alibpython
, como las extensiones de C de la biblioteca estándar construida por la sección*shared*
deModules/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.) sinPY_SSIZE_T_CLEAN
definido ahora lanza una advertenciaDeprecationWarning
. 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 dePyType_GenericAlloc()
a las funciones de más bajo nivel,PyObject_Init()
yPyObject_INIT()
. Esto hace que los tipos creados mediantePyType_FromSpec()
se comporten como otras clases en el código gestionado.Statically allocated types no se ve afectado.
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 aPyObject_New
,PyObject_NewVar()
,PyObject_GC_New()
,PyObject_GC_NewVar()
, o cualquier otro asignador personalizado que usePyObject_Init()
oPyObject_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, incluyendotp_finalize
(Py_TPFLAGS_HAVE_FINALIZE
ya no se verifica antes de leertp_finalize
).(Contribución de Antoine Pitrou en bpo-32388.)
Las funciones
PyNode_AddChild()
yPyParser_AddToken()
ahora aceptan dos argumentosint
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 herramientasgendef
ydlltool
, 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 quepythonXY.lib
, que generalmente es el directoriolibs
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
yreturn
.Eliminados los códigos de operación
BREAK_LOOP
,CONTINUE_LOOP
,SETUP_LOOP
ySETUP_EXCEPT
. Agregados los nuevos códigos de operaciónROT_FOUR
,BEGIN_FINALLY
,CALL_FINALLY
yPOP_FINALLY
. Modificados los códigos de operaciónEND_FINALLY
yWITH_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 cicloasync 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.)
Notable changes in Python 3.8.2¶
Fixed a regression with the ignore
callback of shutil.copytree()
.
The argument types are now str and List[str] again.
(Contributed by Manuel Barkhau and Giampaolo Rodola in gh-83571.)
Notable changes in Python 3.8.3¶
The constant values of future flags in the __future__
module
are updated in order to prevent collision with compiler flags. Previously
PyCF_ALLOW_TOP_LEVEL_AWAIT
was clashing with CO_FUTURE_DIVISION
.
(Contributed by Batuhan Taskaya in gh-83743)
Cambios notables en Python 3.8.8¶
Las versiones anteriores de Python permitían usar tanto ;
como &
como separadores de parámetros de consulta en urllib.parse.parse_qs()
y urllib.parse.parse_qsl()
. Debido a problemas de seguridad y para cumplir con las recomendaciones más recientes del W3C, esto se ha cambiado para permitir solo una clave separadora, con &
como valor predeterminado. Este cambio también afecta a cgi.parse()
y cgi.parse_multipart()
ya que utilizan las funciones afectadas internamente. Para obtener más detalles, consulte su documentación respectiva. (Contribuido por Adam Goldschmidt, Senthil Kumaran y Ken Jin en 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 gh-87451)
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 gh-85272, 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)
Cambios notables en Python 3.8.1¶
Cambios en la API de Python¶
A partir de Python 3.8.12, el módulo ipaddress
ya no acepta ceros a la izquierda en las cadenas de direcciones IPv4. Los ceros iniciales son ambiguos y algunas bibliotecas los interpretan como notación octal. Por ejemplo, la función heredada socket.inet_aton()
trata los ceros iniciales como notación octal. La implementación glibc del inet_pton()
moderno no acepta ceros a la izquierda.
(Contribuido originalmente por Christian Heimes en bpo-36384, y actualizado a 3.8 por 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
, andshutil.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 aDeprecationWarning
. In Python 3.14, the default will switch to'data'
. (Contributed by Petr Viktorin in PEP 706.)