Nota

¡Ayúdanos a traducir la documentación oficial de Python al Español! Puedes encontrar más información en Como contribuir. Ayuda a acercar Python a más personas de habla hispana.

Qué hay de nuevo en Python 3.2

Autor

Raymond Hettinger

Este artículo explica las nuevas características de Python 3.2 en comparación con 3.1. Python 3.2 se lanzó el 20 de febrero de 2011. Se centra en algunos aspectos destacados y ofrece algunos ejemplos. Para obtener detalles completos, consulte el archivo Misc/NEWS.

Ver también

PEP 392 - Calendario de Publicación Python 3.2

PEP 384: Definición de un ABI estable

En el pasado, los módulos de extensión creados para una versión de Python a menudo no se podían usar con otras versiones de Python. Particularmente en Windows, cada lanzamiento de funciones de Python requería reconstruir todos los módulos de extensión que uno quería usar. Este requisito fue el resultado del acceso gratuito a los componentes internos del intérprete de Python que los módulos de extensión podían usar.

Con Python 3.2, está disponible un enfoque alternativo: los módulos de extensión que se restringen a una API limitada (al definir Py_LIMITED_API) no pueden usar muchas de las funciones internas, pero están restringidos a un conjunto de funciones API que se promete serán estables para varias versiones. Como consecuencia, los módulos de extensión creados para 3.2 en ese modo también funcionarán con 3.3, 3.4, etc. Los módulos de extensión que hacen uso de los detalles de las estructuras de memoria aún se pueden construir, pero deberán recompilarse para cada lanzamiento de funciones.

Ver también

PEP 384 - Definición de un ABI estable

PEP escrito por Martin von Löwis.

PEP 389: Módulo de análisis sintáctico (Parser) de línea de comandos Argparse

Se introdujo un nuevo módulo para el análisis de la línea de comandos, argparse, para superar las limitaciones de optparse que no brindaba soporte para argumentos posicionales (no solo opciones), subcomandos, opciones requeridas y otros patrones comunes para especificar y validar opciones.

Este módulo ya ha tenido un éxito generalizado en la comunidad como módulo de terceros. Con más funciones que su predecesor, el módulo argparse es ahora el módulo preferido para el procesamiento de la línea de comandos. El módulo más antiguo todavía se mantiene disponible debido a la gran cantidad de código heredado que depende de él.

Aquí hay un analizador de ejemplo comentado que muestra características de cómo limitar los resultados a un conjunto de opciones, especificar un metavar en la pantalla de ayuda, validar que uno o más argumentos posicionales están presentes y hacer una opción requerida:­:

import argparse
parser = argparse.ArgumentParser(
            description = 'Manage servers',         # main description for help
            epilog = 'Tested on Solaris and Linux') # displayed after help
parser.add_argument('action',                       # argument name
            choices = ['deploy', 'start', 'stop'],  # three allowed values
            help = 'action on each target')         # help msg
parser.add_argument('targets',
            metavar = 'HOSTNAME',                   # var name used in help msg
            nargs = '+',                            # require one or more targets
            help = 'url for target machines')       # help msg explanation
parser.add_argument('-u', '--user',                 # -u or --user option
            required = True,                        # make it a required argument
            help = 'login as user')

Ejemplo de llamada al analizador en una cadena de caracteres de comandos:

>>> cmd = 'deploy sneezy.example.com sleepy.example.com -u skycaptain'
>>> result = parser.parse_args(cmd.split())
>>> result.action
'deploy'
>>> result.targets
['sneezy.example.com', 'sleepy.example.com']
>>> result.user
'skycaptain'

Ejemplo de ayuda generada automáticamente por el analizador:

>>> parser.parse_args('-h'.split())

usage: manage_cloud.py [-h] -u USER
                       {deploy,start,stop} HOSTNAME [HOSTNAME ...]

Manage servers

positional arguments:
  {deploy,start,stop}   action on each target
  HOSTNAME              url for target machines

optional arguments:
  -h, --help            show this help message and exit
  -u USER, --user USER  login as user

Tested on Solaris and Linux

Una característica especialmente agradable de argparse es la capacidad de definir sub-analizadores (subparsers), cada uno con sus propios patrones de argumentos y pantallas de ayuda:

import argparse
parser = argparse.ArgumentParser(prog='HELM')
subparsers = parser.add_subparsers()

parser_l = subparsers.add_parser('launch', help='Launch Control')   # first subgroup
parser_l.add_argument('-m', '--missiles', action='store_true')
parser_l.add_argument('-t', '--torpedos', action='store_true')

parser_m = subparsers.add_parser('move', help='Move Vessel',        # second subgroup
                                 aliases=('steer', 'turn'))         # equivalent names
parser_m.add_argument('-c', '--course', type=int, required=True)
parser_m.add_argument('-s', '--speed', type=int, default=0)
$ ./helm.py --help                         # top level help (launch and move)
$ ./helm.py launch --help                  # help for launch options
$ ./helm.py launch --missiles              # set missiles=True and torpedos=False
$ ./helm.py steer --course 180 --speed 5   # set movement parameters

Ver también

PEP 389 - Nuevo módulo de análisis de línea de comandos

PEP escrito por Steven Bethard.

Actualizar el código de optparse para obtener detalles sobre las diferencias con optparse.

PEP 391: Configuración basada en diccionario para Logging

El módulo logging proporcionó dos tipos de configuración, un estilo con llamadas de función para cada opción y otro estilo guiado por un archivo externo guardado en formato ConfigParser. Esas opciones no proporcionaron la flexibilidad para crear configuraciones a partir de archivos JSON o YAML, ni admitieron la configuración incremental, que es necesaria para especificar las opciones del logger desde una línea de comandos.

Para permitir un estilo más flexible, el módulo ahora ofrece logging.config.dictConfig() para especificar la configuración de logging con diccionarios simples de Python. Las opciones de configuración incluyen formateadores, gestores, filtros y loggers. Aquí hay un ejemplo funcional de un diccionario de configuración:

{"version": 1,
 "formatters": {"brief": {"format": "%(levelname)-8s: %(name)-15s: %(message)s"},
                "full": {"format": "%(asctime)s %(name)-15s %(levelname)-8s %(message)s"}
                },
 "handlers": {"console": {
                   "class": "logging.StreamHandler",
                   "formatter": "brief",
                   "level": "INFO",
                   "stream": "ext://sys.stdout"},
              "console_priority": {
                   "class": "logging.StreamHandler",
                   "formatter": "full",
                   "level": "ERROR",
                   "stream": "ext://sys.stderr"}
              },
 "root": {"level": "DEBUG", "handlers": ["console", "console_priority"]}}

Si ese diccionario está almacenado en un archivo llamado conf.json, se puede cargar y llamar con un código como este:

>>> import json, logging.config
>>> with open('conf.json') as f:
...     conf = json.load(f)
...
>>> logging.config.dictConfig(conf)
>>> logging.info("Transaction completed normally")
INFO    : root           : Transaction completed normally
>>> logging.critical("Abnormal termination")
2011-02-17 11:14:36,694 root            CRITICAL Abnormal termination

Ver también

PEP 391 - Configuración basada en diccionario para Logging

PEP escrito por Vinay Sajip.

PEP 3148: El módulo concurrent.futures

El código para crear y administrar la concurrencia se está recopilando en un nuevo espacio de nombres de nivel superior, concurrent. Su primer miembro es un paquete futures que proporciona una interfaz uniforme de alto nivel para administrar hilos y procesos.

El diseño de concurrent.futures se inspiró en el paquete java.util.concurrent. En ese modelo, una llamada en ejecución y su resultado están representados por un objeto Future que abstrae características comunes a hilos, procesos y llamadas a procedimientos remotos. Ese objeto admite verificaciones de estado (en ejecución o terminadas), tiempos de espera, cancelaciones, agregar devoluciones de llamada y acceso a resultados o excepciones.

El agregado principal del nuevo módulo es un par de clases ejecutoras para lanzar y administrar llamadas. El objetivo de los ejecutores es facilitar el uso de las herramientas existentes para realizar llamadas en paralelo. Ahorran el esfuerzo necesario para configurar un grupo de recursos, lanzar las llamadas, crear una cola de resultados, agregar gestión de tiempo de espera y limitar la cantidad total de hilos, procesos o llamadas a procedimientos remotos.

Idealmente, cada aplicación debería compartir un solo ejecutor en varios componentes para que los límites de procesos e hilos se puedan administrar de forma centralizada. Esto resuelve el desafío de diseño que surge cuando cada componente tiene su propia estrategia competitiva para la gestión de recursos.

Ambas clases comparten una interfaz común con tres métodos: submit() para programar un invocable y retornar un objeto Future map() para programar muchas llamadas asincrónicas a la vez, y shutdown() para liberar recursos. La clase es un context manager y se puede usar en una declaración with para asegurar que los recursos se liberen automáticamente cuando los futuros actualmente pendientes terminan de ejecutarse.

Un ejemplo simple de ThreadPoolExecutor es un lanzamiento de cuatro hilos paralelos para copiar archivos:

import concurrent.futures, shutil
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as e:
    e.submit(shutil.copy, 'src1.txt', 'dest1.txt')
    e.submit(shutil.copy, 'src2.txt', 'dest2.txt')
    e.submit(shutil.copy, 'src3.txt', 'dest3.txt')
    e.submit(shutil.copy, 'src3.txt', 'dest4.txt')

Ver también

PEP 3148 - Futuros – Ejecutar Cómputos Asincrónicos

PEP escrito por Brian Quinlan.

Código para lecturas de URL en paralelo con grupos de hilos, un ejemplo que usa hilos para buscar varias páginas web en paralelo.

Código para calcular números primos en paralelo, un ejemplo demostrando ProcessPoolExecutor.

PEP 3147: Directorios del repositorio de PYC

El esquema de Python para almacenar en caché bytecode en archivos .pyc no funcionó bien en entornos con múltiples intérpretes de Python. Si un intérprete encontrara un archivo en caché creado por otro intérprete, volvería a compilar la fuente y sobrescribiría el archivo en caché, perdiendo así los beneficios del almacenamiento en caché.

El problema de las «peleas de pyc» se ha vuelto más pronunciado a medida que se ha convertido en un lugar común para las distribuciones de Linux enviadas con múltiples versiones de Python. Estos conflictos también surgen con alternativas de CPython como Unladen Swallow.

Para resolver este problema, el mecanismo de importación de Python se ha ampliado para utilizar nombres de archivo distintos para cada intérprete. En lugar de que Python 3.2 y Python 3.3 y Unladen Swallow compitan por un archivo llamado «mymodule.pyc», ahora buscarán «mymodule.cpython-32.pyc», «mymodule.cpython-33.pyc» y «mymodule .unladen10.pyc». Y para evitar que todos estos nuevos archivos abarroten los directorios de origen, los archivos pyc ahora se recopilan en un directorio «__pycache__» almacenado en el directorio del paquete.

Aparte de los nombres de archivo y directorios de destino, el nuevo esquema tiene algunos aspectos que son visibles para el programador:

  • Los módulos importados ahora tienen un atributo __cached__ que almacena el nombre del archivo real que se importó:

    >>> import collections
    >>> collections.__cached__ 
    'c:/py32/lib/__pycache__/collections.cpython-32.pyc'
    
  • La etiqueta que es única para cada intérprete es accesible desde el módulo imp:

    >>> import imp
    >>> imp.get_tag() 
    'cpython-32'
    
  • Los scripts que intentan deducir el nombre del archivo de origen del archivo importado ahora deben ser más inteligentes. Ya no es suficiente simplemente quitar la «c» final del nombre de archivo «.pyc». En su lugar, use las nuevas funciones del módulo imp:

    >>> imp.source_from_cache('c:/py32/lib/__pycache__/collections.cpython-32.pyc')
    'c:/py32/lib/collections.py'
    >>> imp.cache_from_source('c:/py32/lib/collections.py') 
    'c:/py32/lib/__pycache__/collections.cpython-32.pyc'
    
  • Los módulos py_compile y compileall se han actualizado para reflejar la nueva convención de nomenclatura y el directorio de destino. La invocación por línea de comandos de compileall tiene nuevas opciones: -i para especificar una lista de archivos y directorios para compilar y -b que hace que los archivos bytecode se escriban en su ubicación heredada en lugar de __pycache__.

  • El módulo importlib.abc se ha actualizado con una nueva clase base abstracta para cargar archivos bytecode. Las ABC (por sus siglas en inglés abstract base class) obsoletas, PyLoader y PyPycLoader, han sido deprecadas (las instrucciones sobre cómo mantener la compatibilidad con Python 3.1 se incluyen con la documentación).

Ver también

PEP 3147 - Directorio del repositorio PYC

PEP escrito por Barry Warsaw.

PEP 3149: Archivos .so con etiquetado de versión para ABI

El directorio del repositorio PYC permite la ubicación conjunta de varios archivos de cache bytecode. Este PEP implementa un mecanismo similar para los archivos de objetos compartidos dándoles un directorio común y nombres distintos para cada versión.

El directorio común es «pyshared» y los nombres de los archivos se diferencian identificando la implementación de Python (como CPython, PyPy, Jython, etc.), los números de versión principal y secundaria, y las banderas de compilación opcionales (como «d» para debug, «m» para pymalloc, «u» para ancho-unicode). Para un paquete arbitrario «foo», se verán estos archivos cuando se instala el paquete de distribución:

/usr/share/pyshared/foo.cpython-32m.so
/usr/share/pyshared/foo.cpython-33md.so

En Python mismo, las etiquetas son accesibles desde funciones en el módulo sysconfig:

>>> import sysconfig
>>> sysconfig.get_config_var('SOABI')       # find the version tag
'cpython-32mu'
>>> sysconfig.get_config_var('EXT_SUFFIX')  # find the full filename extension
'.cpython-32mu.so'

Ver también

PEP 3149 - PEP 3149: Archivos .so con etiquetado de versión para ABI

PEP escrito por Barry Warsaw.

PEP 3333: Interfaz de puerta de enlace del servidor web Python v1.0.1

Este PEP informativo aclara cómo el protocolo WSGI debe gestionar los problemas de bytes/texto. El desafío es que el manejo de cadenas de caracteres en Python 3 se maneja de manera más conveniente con el tipo str aunque el protocolo HTTP está orientado a bytes.

El PEP diferencia las llamadas cadenas nativas que se utilizan para los encabezados y metadatos de solicitud/respuesta (request/response) frente a las cadenas de bytes que se utilizan para los cuerpos de las solicitudes y respuestas.

Las cadenas nativas son siempre de tipo str pero están restringidas a puntos de código entre U+0000 * hasta *U+00FF que se pueden traducir a bytes usando la codificación Latin-1. Estas cadenas de caracteres se utilizan para las claves y valores en el diccionario de entorno y para los encabezados y estados de respuesta en la función start_response(). Deben seguir RFC 2616 con respecto a la codificación. Es decir, deben tener caracteres ISO-8859-1 o utilizar codificación MIME RFC 2047.

Para los desarrolladores que portan aplicaciones WSGI desde Python 2, estos son los puntos destacados:

  • Si la aplicación ya usó cadenas para encabezados en Python 2, no es necesario ningún cambio.

  • Si, en cambio, la aplicación codificó encabezados de salida o decodificó encabezados de entrada, entonces los encabezados deberán volver a codificarse en Latin-1. Por ejemplo, un encabezado de salida codificado en utf-8 usaba h.encode('utf-8'), ahora se necesita convertir de bytes a cadenas nativas usando h.encode('utf-8').decode('latin-1').

  • Los valores proporcionados por una aplicación o enviados mediante el método write() deben ser cadenas de bytes. La función start_response() y el entorno deben usar cadenas nativas. Los dos no se pueden mezclar.

Para los implementadores de servidores que escriben rutas de CGI a WSGI u otros protocolos de estilo CGI, los usuarios deben poder acceder al entorno utilizando cadenas nativas, aunque la plataforma subyacente pueda tener una convención diferente. Para cerrar esta brecha, el módulo wsgiref tiene una nueva función, wsgiref.handlers.read_environ() para transcodificar variables CGI de os.environ en cadenas nativas y retornar un nuevo diccionario.

Ver también

PEP 3333 - Interfaz de puerta de enlace del servidor web Python v1.0.1

PEP escrito por Phillip Eby.

Otros cambios de lenguaje

Algunos cambios más pequeños realizados en el lenguaje central de Python son:

  • El formato de cadena de caracteres para format() y str.format() obtuvo nuevas capacidades para el carácter de formato #. Anteriormente, para enteros en binario, octal o hexadecimal, hacía que la salida tuviera el prefijo “0b”, “0o” o “0x” respectivamente. Ahora también puede manejar flotantes, complejos y decimales, lo que hace que la salida siempre tenga un punto decimal, incluso cuando no le siguen dígitos.

    >>> format(20, '#o')
    '0o24'
    >>> format(12.34, '#5.0f')
    '  12.'
    

    (Sugerido por Mark Dickinson e implementado por Eric Smith en bpo-7094.)

  • También hay un nuevo método str.format_map() que amplía las capacidades del método existente str.format() al aceptar objetos arbitrarios mapping. Este nuevo método hace posible usar formato de cadena de caracteres con cualquiera de los muchos objetos similares a diccionarios de Python, como defaultdict, Shelf, ConfigParser, o dbm. También es útil con subclases personalizadas dict que normalizan claves antes de la búsqueda o que proporcionan un método __missing__() para claves desconocidas:

    >>> import shelve
    >>> d = shelve.open('tmp.shl')
    >>> 'The {project_name} status is {status} as of {date}'.format_map(d)
    'The testing project status is green as of February 15, 2011'
    
    >>> class LowerCasedDict(dict):
    ...     def __getitem__(self, key):
    ...         return dict.__getitem__(self, key.lower())
    >>> lcd = LowerCasedDict(part='widgets', quantity=10)
    >>> 'There are {QUANTITY} {Part} in stock'.format_map(lcd)
    'There are 10 widgets in stock'
    
    >>> class PlaceholderDict(dict):
    ...     def __missing__(self, key):
    ...         return '<{}>'.format(key)
    >>> 'Hello {name}, welcome to {location}'.format_map(PlaceholderDict())
    'Hello <name>, welcome to <location>'
    

(Sugerido por Raymond Hettinger e implementado por Eric Smith en bpo-6081.)

  • El intérprete ahora puede iniciarse con una opción silenciosa, -q, para evitar que la información de copyright y versión se muestre en el modo interactivo. La opción se puede introspectar usando el atributo sys.flags:

    $ python -q
    >>> sys.flags
    sys.flags(debug=0, division_warning=0, inspect=0, interactive=0,
    optimize=0, dont_write_bytecode=0, no_user_site=0, no_site=0,
    ignore_environment=0, verbose=0, bytes_warning=0, quiet=1)
    

    (Contribución de Marcin Wojdyr en bpo-1772833).

  • La función hasattr() funciona llamando a getattr() y detectando si se lanza una excepción. Esta técnica le permite detectar métodos creados dinámicamente por __getattr__() o __getattribute__() que de otra manera estarían ausentes en el diccionario de la clase. Anteriormente, hasattr detectaba cualquier excepción, posiblemente enmascarando errores genuinos. Ahora, hasattr se ha ajustado para capturar solo AttributeError y dejar que otras excepciones pasen:

    >>> class A:
    ...     @property
    ...     def f(self):
    ...         return 1 // 0
    ...
    >>> a = A()
    >>> hasattr(a, 'f')
    Traceback (most recent call last):
      ...
    ZeroDivisionError: integer division or modulo by zero
    

    (Descubierto por Yury Selivanov y arreglado por Benjamin Peterson; bpo-9666.)

  • La str() de un número flotante o complejo ahora es el mismo que su repr(). Anteriormente, el formulario str() era más corto, pero eso solo causaba confusión y ya no es necesario ahora que el más corto posible repr() se muestra por defecto:

    >>> import math
    >>> repr(math.pi)
    '3.141592653589793'
    >>> str(math.pi)
    '3.141592653589793'
    

    (Propuesto e implementado por Mark Dickinson; bpo-9337.)

  • Los objetos memoryview ahora tienen un método release() y ahora también admiten el protocolo de gestión de contexto. Esto permite la liberación oportuna de los recursos adquiridos al solicitar un búfer del objeto original.

    >>> with memoryview(b'abcdefgh') as v:
    ...     print(v.tolist())
    [97, 98, 99, 100, 101, 102, 103, 104]
    

    (Añadido por Antoine Pitrou; bpo-9757.)

  • Anteriormente, era ilegal eliminar un nombre del espacio de nombres local si aparece como una variable libre en un bloque anidado:

    def outer(x):
        def inner():
            return x
        inner()
        del x
    

    Esto ahora está permitido. Recuerde que el objetivo de una cláusula except se borra, por lo que este código que solía funcionar con Python 2.6, lanza un SyntaxError con Python 3.1 y ahora funciona nuevamente:

    def f():
        def print_error():
            print(e)
        try:
            something
        except Exception as e:
            print_error()
            # implicit "del e" here
    

    (Ver bpo-4617.)

  • La herramienta interna structsequence ahora crea subclases de tupla. Esto significa que las estructuras C como las retornadas por os.stat(), time.gmtime(), y sys.version_info ahora funcionan como named tuple y ahora trabaja con funciones y métodos que esperan una tupla como argumento. Este es un gran paso adelante para hacer que las estructuras de C sean tan flexibles como sus contrapartes de Python puro:

    >>> import sys
    >>> isinstance(sys.version_info, tuple)
    True
    >>> 'Version %d.%d.%d %s(%d)' % sys.version_info 
    'Version 3.2.0 final(0)'
    

    (Sugerido por Arfrever Frehtes Taifersar Arahesis e implementado por Benjamin Peterson en bpo-8413.)

  • Las Warnings ahora son más fáciles de controlar usando la variable de entorno PYTHONWARNINGS como alternativa al uso de -W en la línea de comando:

    $ export PYTHONWARNINGS='ignore::RuntimeWarning::,once::UnicodeWarning::'
    

    (Sugerido por Barry Warsaw e implementado por Philip Jenvey en bpo-7301.)

  • Se ha agregado una nueva categoría de advertencia, ResourceWarning. Se emite cuando se detectan problemas potenciales con el consumo de recursos o la limpieza. Está silenciado de forma predeterminada en las versiones de lanzamiento normales, pero se puede habilitar a través de los medios proporcionados por el módulo warnings o en la línea de comandos.

    Un ResourceWarning se emite en el cierre del intérprete si la lista gc.garbage no está vacía, y si gc.DEBUG_UNCOLLECTABLE está configurado, se imprimen todos los objetos no recolectados. Esto tiene como objetivo informar al programador de que su código contiene problemas de finalización de objetos.

    Un ResourceWarning también se emite cuando un file object se destruye sin haber sido cerrado explícitamente. Si bien el desasignador de dicho objeto asegura que cierra el recurso del sistema operativo subyacente (generalmente, un descriptor de archivo), la demora en desasignar el objeto podría producir varios problemas, especialmente en Windows. A continuación, se muestra un ejemplo de cómo habilitar la advertencia desde la línea de comando:

    $ python -q -Wdefault
    >>> f = open("foo", "wb")
    >>> del f
    __main__:1: ResourceWarning: unclosed file <_io.BufferedWriter name='foo'>
    

    (Agregado por Antoine Pitrou y Georg Brandl en bpo-10093 y bpo-477863.)

  • Los objetos range ahora admiten los métodos index y count. Esto es parte de un esfuerzo para hacer que más objetos implementen completamente la abstract base class collections.Sequence. Como resultado, el lenguaje tendrá una API más uniforme. Además, los objetos range ahora admiten índices negativos y de corte, incluso con valores mayores que sys.maxsize. Esto hace que range sea más interoperable con listas:

    >>> range(0, 100, 2).count(10)
    1
    >>> range(0, 100, 2).index(10)
    5
    >>> range(0, 100, 2)[5]
    10
    >>> range(0, 100, 2)[0:5]
    range(0, 10, 2)
    

    (Contribuido por Daniel Stutzbach en bpo-9213, por Alexander Belopolsky en bpo-2690, y por Nick Coghlan en bpo-10889.)

  • Se resucitó la función incorporada callable() de Py2.x. Proporciona una alternativa concisa y legible al uso de una abstract base class en una expresión como isinstance(x, collections.Callable):

    >>> callable(max)
    True
    >>> callable(20)
    False
    

    (Ver bpo-10518.)

  • El mecanismo de importación de Python ahora puede cargar módulos instalados en directorios con caracteres no ASCII en el nombre de la ruta. Esto resolvió un problema agravante con los directorios de inicio para los usuarios con caracteres no ASCII en sus nombres de usuario.

(Trabajo extenso requerido por Victor Stinner en bpo-9425.)

Módulos nuevos, mejorados y obsoletos

La biblioteca estándar de Python ha sido objeto de importantes esfuerzos de mantenimiento y mejoras de calidad.

La mayor novedad para Python 3.2 es que el paquete email, el módulo mailbox y los módulos nntplib ahora funcionan correctamente con el modelo de bytes/texto en Python 3. Por primera vez , existe un manejo correcto de mensajes con codificaciones mixtas.

En toda la biblioteca estándar, se ha prestado más atención a las codificaciones y los problemas de texto frente a bytes. En particular, las interacciones con el sistema operativo ahora son más capaces de intercambiar datos que no son ASCII mediante la codificación MBCS de Windows, codificaciones con reconocimiento de configuración regional o UTF-8.

Otro logro importante es la adición de un soporte sustancialmente mejor para conexiones SSL y certificados de seguridad.

Además, más clases ahora implementan context manager para soportar una conveniente y confiable limpieza de recursos usando una declaración with.

email

La usabilidad del paquete email en Python 3 se ha solucionado principalmente gracias a los amplios esfuerzos de R. David Murray. El problema era que los correos electrónicos generalmente se leen y almacenan en forma de bytes en lugar de texto str, y pueden contener múltiples codificaciones dentro de un solo correo electrónico. Por lo tanto, el paquete email tuvo que ampliarse para analizar y generar mensajes de correo electrónico en formato de bytes.

  • Nuevas funciones message_from_bytes() y message_from_binary_file(), y nuevas clases BytesFeedParser y BytesParser permiten mensajes de datos en binario para ser analizados (parsed) en objetos modelados.

  • Dada la entrada de bytes al modelo, get_payload() decodificará por defecto un cuerpo de mensaje que tiene un Content-Transfer-Encoding de 8bit usando el juego de caracteres especificado en el encabezados MIME y retorna la cadena de caracteres resultante.

  • Dada la entrada de bytes al modelo, Generator convertirá los cuerpos de los mensajes que tengan un Content-Transfer-Encoding de 8bit para tener en su lugar un 7bitContent-Transfer-Encoding.

    Los encabezados con bytes no codificados que no sean ASCII se consideran RFC 2047-codificados utilizando el juego de caracteres unknown-8bit.

  • Una nueva clase BytesGenerator produce bytes como salida, conservando cualquier dato no ASCII sin cambios que estuviera presente en la entrada utilizada para construir el modelo, incluidos los cuerpos de los mensajes con un Content-Transfer-Encoding de 8bit.

  • La clase smtplibSMTP ahora acepta una cadena de bytes para el argumento msg para el método sendmail(), y un nuevo método, send_message() acepta un objeto Message y opcionalmente puede obtener las direcciones from_addr y to_addrs directamente del objeto.

(Propuesto e implementado por R. David Murray, bpo-4661 y bpo-10321.)

elementtree

El paquete xml.etree.ElementTree y su contraparte xml.etree.cElementTree se han actualizado a la versión 1.3.

Se han agregado varias nuevas y útiles funciones y métodos:

Dos métodos que han sido deprecados:

  • xml.etree.ElementTree.getchildren() usar list(elem) en su lugar.

  • xml.etree.ElementTree.getiterator() usar Element.iter en su lugar.

Para obtener más información sobre la actualización, consulte Introducing ElementTree en el sitio web de Fredrik Lundh.

(Contribución de Florent Xicluna y Fredrik Lundh, bpo-6472.)

functools

  • El módulo functools incluye un nuevo decorador para almacenar en caché las llamadas a funciones. functools.lru_cache() puede guardar consultas repetidas en un recurso externo siempre que se espere que los resultados sean los mismos.

    Por ejemplo, agregar un decorador de almacenamiento en caché a una función de consulta de base de datos puede ahorrar accesos a la base de datos para búsquedas populares:

    >>> import functools
    >>> @functools.lru_cache(maxsize=300)
    ... def get_phone_number(name):
    ...     c = conn.cursor()
    ...     c.execute('SELECT phonenumber FROM phonelist WHERE name=?', (name,))
    ...     return c.fetchone()[0]
    
    >>> for name in user_requests:        
    ...     get_phone_number(name)        # cached lookup
    

    Para ayudar a elegir un tamaño de caché efectivo, la función encapsulada está instrumentada para rastrear estadísticas de caché:

    >>> get_phone_number.cache_info()     
    CacheInfo(hits=4805, misses=980, maxsize=300, currsize=300)
    

    Si la tabla phonelist se actualiza, el contenido desactualizado de la caché se puede borrar con:

    >>> get_phone_number.cache_clear()
    

    (Contribución de Raymond Hettinger e incorporando ideas de diseño de Jim Baker, Miki Tebeka, y Nick Coghlan; ver recipe 498245, recipe 577479, bpo-10586, y bpo-10593.)

  • El decorador functools.wraps() ahora agrega un atributo __wrapped__ que apunta a la función invocable original. Esto permite la introspección de funciones envueltas (wrapped). También copia __annotations__ si está definido. Y ahora también omite elegantemente los atributos faltantes como __doc__ que podrían no estar definidos para el invocable envuelto.

    En el ejemplo anterior, la caché se puede eliminar recuperando la función original:

    >>> get_phone_number = get_phone_number.__wrapped__    # uncached function
    

    (Por Nick Coghlan y Terrence Cole; bpo-9567, bpo-3445, y bpo-8814.)

  • Para ayudar a escribir clases con métodos de comparación enriquecidos, un nuevo decorador functools.total_ordering() usará métodos de igualdad y desigualdad existentes para completar los métodos restantes.

    Por ejemplo, suministrar __eq__ y __lt__ permitirá que total_ordering() complete __le__, __gt__ and __ge__:

    @total_ordering
    class Student:
        def __eq__(self, other):
            return ((self.lastname.lower(), self.firstname.lower()) ==
                    (other.lastname.lower(), other.firstname.lower()))
    
        def __lt__(self, other):
            return ((self.lastname.lower(), self.firstname.lower()) <
                    (other.lastname.lower(), other.firstname.lower()))
    

    Con el decorador total_ordering, los métodos de comparación restantes se completan automáticamente.

    (Contribución por Raymond Hettinger.)

  • Para ayudar en la migración de programas desde Python 2, la función functools.cmp_to_key() convierte una función de comparación de estilo antiguo en la nueva key function:

    >>> # locale-aware sort order
    >>> sorted(iterable, key=cmp_to_key(locale.strcoll)) 
    

    Para obtener ejemplos de ordenación y un breve tutorial, consulte el tutorial Sorting HowTo.

    (Contribución por Raymond Hettinger.)

itertools

  • El módulo itertools tiene una nueva función accumulate() modelada en el operador scan de APL y la función accumulate de Numpy:

    >>> from itertools import accumulate
    >>> list(accumulate([8, 2, 50]))
    [8, 10, 60]
    
    >>> prob_dist = [0.1, 0.4, 0.2, 0.3]
    >>> list(accumulate(prob_dist))      # cumulative probability distribution
    [0.1, 0.5, 0.7, 1.0]
    

    Para un ejemplo usando accumulate(), vea los ejemplos para el módulo aleatorio.

    (Contribución de Raymond Hettinger e incorporando sugerencias de diseño de Mark Dickinson.)

collections

  • La clase collections.Counter ahora tiene dos formas de resta in situ, el operador existente -= para saturación de resta y el nuevo método subtract() para la resta regular. El primero es adecuado para muticonjunto que solo tienen recuentos positivos, y el último es más adecuado para casos de uso que permiten recuentos negativos:

    >>> from collections import Counter
    >>> tally = Counter(dogs=5, cats=3)
    >>> tally -= Counter(dogs=2, cats=8)    # saturating subtraction
    >>> tally
    Counter({'dogs': 3})
    
    >>> tally = Counter(dogs=5, cats=3)
    >>> tally.subtract(dogs=2, cats=8)      # regular subtraction
    >>> tally
    Counter({'dogs': 3, 'cats': -5})
    

    (Contribución por Raymond Hettinger.)

  • La clase collections.OrderedDict tiene un nuevo método move_to_end() que toma una clave existente y mueve a la primera o última posición de la secuencia ordenada.

    El valor predeterminado es mover un elemento a la última posición. Esto es equivalente a renovar una entrada con od[k] = od.pop(k).

    Una operación de mover al final rápida es útil para volver a secuenciar entradas. Por ejemplo, se puede usar un diccionario ordenado para rastrear el orden de acceso a las entradas por antigüedad desde la más antigua hasta la más reciente.

    >>> from collections import OrderedDict
    >>> d = OrderedDict.fromkeys(['a', 'b', 'X', 'd', 'e'])
    >>> list(d)
    ['a', 'b', 'X', 'd', 'e']
    >>> d.move_to_end('X')
    >>> list(d)
    ['a', 'b', 'd', 'e', 'X']
    

    (Contribución por Raymond Hettinger.)

  • La clase collections.deque desarrolló dos métodos nuevos count() y reverse() que los hacen más intercambiables con los objetos list :

    >>> from collections import deque
    >>> d = deque('simsalabim')
    >>> d.count('s')
    2
    >>> d.reverse()
    >>> d
    deque(['m', 'i', 'b', 'a', 'l', 'a', 's', 'm', 'i', 's'])
    

    (Contribución por Raymond Hettinger.)

threading

El módulo threading tiene una nueva clase Barrier de sincronización para hacer que varios hilos esperen hasta que todos hayan alcanzado un punto de barrera común. Las barreras son útiles para asegurarse de que una tarea con múltiples condiciones previas no se ejecute hasta que se completen todas las tareas predecesoras.

Las barreras pueden trabajar con un número arbitrario de hilos. Esto es una generalización de barrera informática que se define solo para dos hilos.

Implementado como una barrera cíclica de dos fases, los objetos Barrier son adecuados para su uso en bucles. Las fases separadas de llenado y drenaje aseguran que todos los hilos se liberen (drenan) antes de que cualquiera de ellos pueda retornar y volver a entrar en la barrera. La barrera se restablece completamente después de cada ciclo.

Ejemplo de uso de barreras:

from threading import Barrier, Thread

def get_votes(site):
    ballots = conduct_election(site)
    all_polls_closed.wait()        # do not count until all polls are closed
    totals = summarize(ballots)
    publish(site, totals)

all_polls_closed = Barrier(len(sites))
for site in sites:
    Thread(target=get_votes, args=(site,)).start()

En este ejemplo, la barrera impone una regla de que los votos no se pueden contar en ningún lugar de votación hasta que se cierren todas las urnas. Observe cómo una solución con una barrera es similar a una con threading.Thread.join(), pero los hilos se mantienen vivos y continúan trabajando (resumiendo las papeletas) después de que se cruza el punto de la barrera.

Si alguna de las tareas predecesoras puede bloquearse o retrasarse, se puede crear una barrera con un parámetro opcional timeout. Luego, si el período de tiempo de espera transcurre antes de que todas las tareas predecesoras alcancen el punto de barrera, se liberan todos los hilos en espera y se lanza una excepción BrokenBarrierError:

def get_votes(site):
    ballots = conduct_election(site)
    try:
        all_polls_closed.wait(timeout=midnight - time.now())
    except BrokenBarrierError:
        lockbox = seal_ballots(ballots)
        queue.put(lockbox)
    else:
        totals = summarize(ballots)
        publish(site, totals)

En este ejemplo, la barrera impone una regla más sólida. Si algunos sitios electorales no terminan antes de la medianoche, la barrera expira y las boletas se sellan y se depositan en una cola para su posterior manejo.

Consulte Barrier Synchronization Patterns para obtener más ejemplos de cómo se pueden usar las barreras en la computación paralela. Además, hay una explicación simple pero completa de las barreras en The Little Book of Semaphores, section 3.6.

(Contribución de Kristján Valur Jónsson con una revisión de API de Jeffrey Yasskin en bpo-8777.)

datetime and time

  • El módulo datetime tiene un nuevo tipo timezone que implementa la interfaz tzinfo retornando un desplazamiento fijo desde UTC y un nombre de zona horaria. Esto hace que sea más fácil crear objetos de fecha y hora que tengan en cuenta la zona horaria:

    >>> from datetime import datetime, timezone
    
    >>> datetime.now(timezone.utc)
    datetime.datetime(2010, 12, 8, 21, 4, 2, 923754, tzinfo=datetime.timezone.utc)
    
    >>> datetime.strptime("01/01/2000 12:00 +0000", "%m/%d/%Y %H:%M %z")
    datetime.datetime(2000, 1, 1, 12, 0, tzinfo=datetime.timezone.utc)
    
  • Además, los objetos timedelta ahora pueden ser multiplicados por objetos float y divididos por objetos float e int. Y los objetos timedelta ahora se pueden dividir entre sí.

  • El método datetime.date.strftime() ya no está restringido a años posteriores a 1900. El nuevo rango de años admitido es de 1000 a 9999 inclusive.

  • Siempre que se utiliza un año de dos dígitos en una tupla de tiempo, la interpretación se rige por time.accept2dyear. El valor predeterminado es True, lo que significa que para un año de dos dígitos, el siglo se calcula de acuerdo con las reglas POSIX que rigen el formato strptime %y.

    A partir de Py3.2, el uso de la heurística de adivinación del siglo emitirá un DeprecationWarning. En su lugar, se recomienda que time.accept2dyear se establezca en False para que se puedan usar rangos de fechas grandes sin suposiciones:

    >>> import time, warnings
    >>> warnings.resetwarnings()      # remove the default warning filters
    
    >>> time.accept2dyear = True      # guess whether 11 means 11 or 2011
    >>> time.asctime((11, 1, 1, 12, 34, 56, 4, 1, 0))
    Warning (from warnings module):
      ...
    DeprecationWarning: Century info guessed for a 2-digit year.
    'Fri Jan  1 12:34:56 2011'
    
    >>> time.accept2dyear = False     # use the full range of allowable dates
    >>> time.asctime((11, 1, 1, 12, 34, 56, 4, 1, 0))
    'Fri Jan  1 12:34:56 11'
    

    Varias funciones ahora tienen rangos de fechas significativamente ampliados. Cuando time.accept2dyear es falso, la función time.asctime() aceptará cualquier año que quepa en un entero C, mientras que las funciones time.mktime() y time.strftime() aceptarán la gama completa admitida por las funciones correspondientes del sistema operativo.

(Contribución de Alexander Belopolsky y Victor Stinner en bpo-1289118, bpo-5094, bpo-6641, bpo-2706, bpo-1777412, bpo-8013, y bpo-10827.)

math

El módulo math se ha actualizado con seis nuevas funciones inspiradas en el estándar C99.

La función isfinite() proporciona una forma rápida y fiable de detectar valores especiales. Retorna True para números regulares y False para Nan o Infinity:

>>> from math import isfinite
>>> [isfinite(x) for x in (123, 4.56, float('Nan'), float('Inf'))]
[True, True, False, False]

La función expm1() calcula e**x-1 para valores pequeños de x sin incurrir en la pérdida de precisión que generalmente acompaña a la resta de cantidades casi iguales:

>>> from math import expm1
>>> expm1(0.013671875)   # more accurate way to compute e**x-1 for a small x
0.013765762467652909

La función erf() calcula una integral de probabilidad o función de error gaussiano. La función de error complementaria, erfc(), es 1 - erf(x):

>>> from math import erf, erfc, sqrt
>>> erf(1.0/sqrt(2.0))   # portion of normal distribution within 1 standard deviation
0.682689492137086
>>> erfc(1.0/sqrt(2.0))  # portion of normal distribution outside 1 standard deviation
0.31731050786291404
>>> erf(1.0/sqrt(2.0)) + erfc(1.0/sqrt(2.0))
1.0

La función gamma() es una extensión continua de la función factorial. Consulte https://es.wikipedia.org/wiki/Funci%C3%B3n_gamma para obtener más detalles. Debido a que la función está relacionada con factoriales, crece incluso para valores pequeños de x, por lo que también hay una función lgamma() para calcular el logaritmo natural de la función gamma:

>>> from math import gamma, lgamma
>>> gamma(7.0)           # six factorial
720.0
>>> lgamma(801.0)        # log(800 factorial)
4551.950730698041

(Contribución de Mark Dickinson.)

abc

El módulo abc ahora admite abstractclassmethod() y abstractstaticmethod().

Estas herramientas permiten definir una abstract base class que requiere un classmethod() o staticmethod() particular para ser implementado:

class Temperature(metaclass=abc.ABCMeta):
    @abc.abstractclassmethod
    def from_fahrenheit(cls, t):
        ...
    @abc.abstractclassmethod
    def from_celsius(cls, t):
        ...

(Parche enviado por Daniel Urban; bpo-5867.)

io

La clase io.BytesIO tiene un nuevo método, getbuffer(), que proporciona una funcionalidad similar a memoryview(). Crea una vista editable de los datos sin hacer una copia. El acceso aleatorio del búfer y la compatibilidad con la notación de sectores son adecuados para la edición in situ:

>>> REC_LEN, LOC_START, LOC_LEN = 34, 7, 11

>>> def change_location(buffer, record_number, location):
...     start = record_number * REC_LEN + LOC_START
...     buffer[start: start+LOC_LEN] = location

>>> import io

>>> byte_stream = io.BytesIO(
...     b'G3805  storeroom  Main chassis    '
...     b'X7899  shipping   Reserve cog     '
...     b'L6988  receiving  Primary sprocket'
... )
>>> buffer = byte_stream.getbuffer()
>>> change_location(buffer, 1, b'warehouse  ')
>>> change_location(buffer, 0, b'showroom   ')
>>> print(byte_stream.getvalue())
b'G3805  showroom   Main chassis    '
b'X7899  warehouse  Reserve cog     '
b'L6988  receiving  Primary sprocket'

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

reprlib

Al escribir un método __repr__() para un contenedor personalizado, es fácil olvidarse de gestionar el caso en el que un miembro hace referencia al contenedor en sí. Los objetos incorporados de Python como list y set manejan la autorreferencia mostrando «…» en la parte recursiva de la cadena de representación.

Para ayudar a escribir tales métodos __repr__(), el módulo reprlib tiene un nuevo decorador, recursive_repr(), para detectar llamadas recursivas a __repr__() y sustituir una cadena marcadora de posición en su lugar:

>>> class MyList(list):
...     @recursive_repr()
...     def __repr__(self):
...         return '<' + '|'.join(map(repr, self)) + '>'
...
>>> m = MyList('abc')
>>> m.append(m)
>>> m.append('x')
>>> print(m)
<'a'|'b'|'c'|...|'x'>

(Contribución de Raymond Hettinger en bpo-9826 y bpo-9840.)

logging

Además de la configuración basada en diccionario descrita anteriormente, el paquete logging tiene muchas otras mejoras.

La documentación de logging se ha aumentado con un tutorial básico, un tutorial avanzado, y un libro de recetas. Estos documentos son la forma más rápida de aprender sobre logging.

La función de configuración logging.basicConfig() adquirió un argumento style para admitir tres tipos diferentes de formato de cadena de caracteres. Su valor predeterminado es «%» para el formato % tradicional, se puede establecer en «{» para el nuevo estilo str.format(), o se puede establecer en «$» para el formato de estilo shell proporcionado por string.Template. Las siguientes tres configuraciones son equivalentes:

>>> from logging import basicConfig
>>> basicConfig(style='%', format="%(name)s -> %(levelname)s: %(message)s")
>>> basicConfig(style='{', format="{name} -> {levelname} {message}")
>>> basicConfig(style='$', format="$name -> $levelname: $message")

Si no se establece ninguna configuración antes de que ocurra un evento de logging, ahora hay una configuración predeterminada que usa una StreamHandler dirigido a sys.stderr para eventos de nivel WARNING o mayor. Anteriormente, un evento que ocurría antes de que se establezca una configuración lanzaba una excepción o eliminaba silenciosamente el evento según el valor de logging.raiseExceptions. El nuevo gestor predeterminado se almacena en logging.lastResort.

El uso de filtros ha sido simplificado. En lugar de crear un objeto Filter, la declaración puede ser cualquier invocable Python que retorna True o False.

Hubo una serie de otras mejoras que agregan flexibilidad y simplifican la configuración. Consulte la documentación del módulo para obtener una lista completa de los cambios en Python 3.2.

csv

El módulo csv ahora admite un nuevo dialecto, unix_dialect, que aplica comillas para todos los campos y un estilo Unix tradicional con '\n' como terminador de línea. El nombre del dialecto registrado es unix.

La clase csv.DictWriter tiene un nuevo método, writeheader() para escribir una fila inicial para documentar los nombres de los campos:

>>> import csv, sys
>>> w = csv.DictWriter(sys.stdout, ['name', 'dept'], dialect='unix')
>>> w.writeheader()
"name","dept"
>>> w.writerows([
...     {'name': 'tom', 'dept': 'accounting'},
...     {'name': 'susan', 'dept': 'Salesl'}])
"tom","accounting"
"susan","sales"

(Nuevo dialecto sugerido por Jay Talbot en bpo-5975, y el nuevo método sugerido por Ed Abraham en bpo-1537721.)

contextlib

Hay una nueva y ligeramente alucinante herramienta ContextDecorator que es útil para crear un context manager que cumple una doble función como decorador de funciones.

Para su comodidad, esta nueva funcionalidad es utilizada por contextmanager() de modo que no se necesita ningún esfuerzo adicional para admitir ambos roles.

La idea básica es que tanto los gestores de contexto como los decoradores de funciones se pueden usar para envoltorios (wrappers) previos y posteriores a la acción. Los gestores de contexto envuelven un grupo de declaraciones usando la declaración with y los decoradores de funciones envuelven un grupo de declaraciones encerradas en una función. Por lo tanto, ocasionalmente es necesario escribir un envoltorio de acción previa o posterior que se pueda usar en cualquiera de los roles.

Por ejemplo, a veces es útil envolver funciones o grupos de declaraciones con un logger que pueda rastrear el tiempo de entrada y el tiempo de salida. En lugar de escribir tanto un decorador de funciones como un gestor de contexto para la tarea, contextmanager() proporciona ambas capacidades en una sola definición:

from contextlib import contextmanager
import logging

logging.basicConfig(level=logging.INFO)

@contextmanager
def track_entry_and_exit(name):
    logging.info('Entering: %s', name)
    yield
    logging.info('Exiting: %s', name)

Anteriormente, esto solo se podía usar como gestor de contexto:

with track_entry_and_exit('widget loader'):
    print('Some time consuming activity goes here')
    load_widget()

Ahora, también se puede usar como decorador:

@track_entry_and_exit('widget loader')
def activity():
    print('Some time consuming activity goes here')
    load_widget()

Tratar de cumplir dos roles a la vez impone algunas limitaciones a la técnica. Los gestores de contexto normalmente tienen la flexibilidad de retornar un argumento utilizable por una instrucción with, pero no hay paralelo para los decoradores de funciones.

En el ejemplo anterior, no hay una forma limpia para que el gestor de contexto track_entry_and_exit retorne una instancia de logging para usar en el cuerpo de las declaraciones adjuntas.

(Contribución de Michael Foord en bpo-9110.)

decimal and fractions

Mark Dickinson diseñó un esquema elegante y eficiente para asegurar que diferentes tipos de datos numéricos tendrán el mismo valor hash siempre que sus valores reales sean iguales (bpo-8188):

assert hash(Fraction(3, 2)) == hash(1.5) == \
       hash(Decimal("1.5")) == hash(complex(1.5, 0))

Algunos de los detalles de hash se exponen a través de un nuevo atributo, sys.hash_info, que describe el ancho de bits del valor hash, el módulo principal, los valores hash para infinity y nan, y el multiplicador utilizado para la parte imaginaria de un número:

>>> sys.hash_info 
sys.hash_info(width=64, modulus=2305843009213693951, inf=314159, nan=0, imag=1000003)

Se ha atenuado una decisión temprana para limitar la interoperabilidad de varios tipos numéricos. Todavía no se admite (y es desaconsejable) tener una mezcla implícita en expresiones aritméticas como Decimal('1.1') + float('1.1') porque este último pierde información en el proceso de construcción del float binario. Sin embargo, dado que el valor de punto flotante existente se puede convertir sin pérdidas a una representación decimal o racional, tiene sentido agregarlos al constructor y admitir comparaciones de tipo mixto.

Cambios similares se hicieron en fractions.Fraction por lo que los métodos from_float() y from_decimal() ya no son necesarios (bpo-8294):

>>> from decimal import Decimal
>>> from fractions import Fraction
>>> Decimal(1.1)
Decimal('1.100000000000000088817841970012523233890533447265625')
>>> Fraction(1.1)
Fraction(2476979795053773, 2251799813685248)

Otro cambio útil para el módulo decimal es que el atributo Context.clamp ahora es público. Esto es útil para crear contextos que se correspondan con los formatos de intercambio decimal especificados en IEEE 754 (ver :8540).

(Contribución de Mark Dickinson y Raymond Hettinger.)

ftp

La clase ftplib.FTP ahora admite el protocolo de gestor de contexto para consumir incondicionalmente las excepciones socket.error y cerrar la conexión FTP cuando haya terminado:

>>> from ftplib import FTP
>>> with FTP("ftp1.at.proftpd.org") as ftp:
        ftp.login()
        ftp.dir()

'230 Anonymous login ok, restrictions apply.'
dr-xr-xr-x   9 ftp      ftp           154 May  6 10:43 .
dr-xr-xr-x   9 ftp      ftp           154 May  6 10:43 ..
dr-xr-xr-x   5 ftp      ftp          4096 May  6 10:43 CentOS
dr-xr-xr-x   3 ftp      ftp            18 Jul 10  2008 Fedora

Otros objetos similares a archivos como mmap.mmap y fileinput.input() también adquirieron gestores de contexto de cierre automático:

with fileinput.input(files=('log1.txt', 'log2.txt')) as f:
    for line in f:
        process(line)

(Contribución de Tarek Ziadé y Giampaolo Rodolà en bpo-4972, y por Georg Brandl en bpo-8046 y bpo-1286.)

La clase FTP_TLS ahora acepta un parámetro context, que es un objeto ssl.SSLContext que permite agrupar opciones de configuración SSL, certificados y claves privadas en una sola (y potencialmente de larga duración) estructura.

(Contribución de Giampaolo Rodolà; bpo-8806.)

popen

Las funciones os.popen() y subprocess.Popen() ahora admiten declaraciones with para el cierre automático de los descriptores de archivo.

(Contribución de Antoine Pitrou y Brian Curtin en bpo-7461 y bpo-10554.)

select

El módulo select ahora presenta un nuevo atributo constante, PIPE_BUF, que da el número mínimo de bytes que están garantizados para no bloquearse cuando select.select() dice que una tubería está lista para escribir.

>>> import select
>>> select.PIPE_BUF  
512

(Disponible en sistemas Unix. Parche de Sébastien Sablé en bpo-9862)

gzip y zipfile

gzip.GzipFile ahora implementa io.BufferedIOBase clase base abstracta (excepto para truncate()). También tiene un método peek() y admite objetos de archivo con rellenos de ceros y que no se pueden buscar.

El módulo gzip también obtiene las funciones compress() y decompress() para facilitar la compresión y descompresión en memoria. Tenga en cuenta que el texto debe codificarse como bytes antes de comprimir y descomprimir:

>>> import gzip
>>> s = 'Three shall be the number thou shalt count, '
>>> s += 'and the number of the counting shall be three'
>>> b = s.encode()                        # convert to utf-8
>>> len(b)
89
>>> c = gzip.compress(b)
>>> len(c)
77
>>> gzip.decompress(c).decode()[:42]      # decompress and convert to text
'Three shall be the number thou shalt count'

(Contribución de Anand B. Pillai en bpo-3488; y de Antoine Pitrou, Nir Aides y Brian Curtin en bpo-9962, bpo-1675951, bpo-7471 y bpo-2846.)

Además, la clase zipfile.ZipExtFile se modificó internamente para representar archivos almacenados dentro de un archivo. La nueva implementación es significativamente más rápida y se puede incluir en un objeto io.BufferedReader para obtener más aceleraciones. También resuelve un problema en el que las llamadas intercaladas a read y readline daban resultados incorrectos.

(Parche enviado por Nir Aides en bpo-7610.)

tarfile

La clase TarFile ahora se puede usar como gestor de contexto. Además, su método add() tiene una nueva opción, filter, que controla qué archivos se agregan y permite editar los metadatos del archivo.

La nueva opción filter reemplaza el parámetro anterior y menos flexible exclude que ahora está deprecado. Si se especifica, el parámetro opcional filter debe ser un keyword argument. La función filter proporcionada por el usuario acepta un objeto TarInfo y retorna un objeto TarInfo actualizado, o si desea que el archivo sea excluido, la función puede retornar None:

>>> import tarfile, glob

>>> def myfilter(tarinfo):
...     if tarinfo.isfile():             # only save real files
...         tarinfo.uname = 'monty'      # redact the user name
...         return tarinfo

>>> with tarfile.open(name='myarchive.tar.gz', mode='w:gz') as tf:
...     for filename in glob.glob('*.txt'):
...         tf.add(filename, filter=myfilter)
...     tf.list()
-rw-r--r-- monty/501        902 2011-01-26 17:59:11 annotations.txt
-rw-r--r-- monty/501        123 2011-01-26 17:59:11 general_questions.txt
-rw-r--r-- monty/501       3514 2011-01-26 17:59:11 prion.txt
-rw-r--r-- monty/501        124 2011-01-26 17:59:11 py_todo.txt
-rw-r--r-- monty/501       1399 2011-01-26 17:59:11 semaphore_notes.txt

(Propuesto por Tarek Ziadé e implementado por Lars Gustäbel en bpo-6856.)

hashlib

El módulo hashlib tiene dos nuevos atributos constantes que enumeran los algoritmos hash garantizados para estar presentes en todas las implementaciones y los disponibles en la implementación actual:

>>> import hashlib

>>> hashlib.algorithms_guaranteed
{'sha1', 'sha224', 'sha384', 'sha256', 'sha512', 'md5'}

>>> hashlib.algorithms_available
{'md2', 'SHA256', 'SHA512', 'dsaWithSHA', 'mdc2', 'SHA224', 'MD4', 'sha256',
'sha512', 'ripemd160', 'SHA1', 'MDC2', 'SHA', 'SHA384', 'MD2',
'ecdsa-with-SHA1','md4', 'md5', 'sha1', 'DSA-SHA', 'sha224',
'dsaEncryption', 'DSA', 'RIPEMD160', 'sha', 'MD5', 'sha384'}

(Sugerido por Carl Chenet en bpo-7418.)

ast

El módulo ast tiene una maravillosa herramienta de propósito general para evaluar cadenas de expresión de forma segura utilizando la sintaxis literal de Python. La función ast.literal_eval() sirve como una alternativa segura a la función incorporada eval() la cual se abusa fácilmente. Python 3.2 agrega bytes y set literales a la lista de tipos admitidos: cadenas de caracteres, bytes, números, tuplas, listas, diccionarios, sets, valores booleanos y None.

>>> from ast import literal_eval

>>> request = "{'req': 3, 'func': 'pow', 'args': (2, 0.5)}"
>>> literal_eval(request)
{'args': (2, 0.5), 'req': 3, 'func': 'pow'}

>>> request = "os.system('do something harmful')"
>>> literal_eval(request)
Traceback (most recent call last):
  ...
ValueError: malformed node or string: <_ast.Call object at 0x101739a10>

(Implementado por Benjamin Peterson y Georg Brandl.)

os

Los diferentes sistemas operativos utilizan varias codificaciones para los nombres de archivo y las variables de entorno. El módulo os proporciona dos funciones nuevas, fsencode() y fsdecode(), para codificar y decodificar nombres de archivo:

>>> import os
>>> filename = 'Sehenswürdigkeiten'
>>> os.fsencode(filename)
b'Sehensw\xc3\xbcrdigkeiten'

Algunos sistemas operativos permiten el acceso directo a bytes codificados en el entorno. Si es así, la constante os.supports_bytes_environ será verdadera.

Para acceder directamente a las variables de entorno codificadas (si está disponible), utilice la nueva función os.getenvb() o utilice os.environb, que es una versión en bytes de os.environ.

(Contribución de Victor Stinner.)

shutil

La función shutil.copytree() tiene dos nuevas opciones:

  • ignore_dangling_symlinks: cuando symlinks=False para que la función copie un archivo apuntado por un enlace simbólico, no el enlace simbólico en sí. Esta opción silenciará el error lanzado si el archivo no existe.

  • copy_function: es un invocable que se utilizará para copiar archivos. shutil.copy2() se usa por defecto.

(Contribución de Tarek Ziadé.)

Además, el módulo shutil ahora admite operaciones de archivado para archivos zip, archivos tar sin comprimir, archivos tar comprimidos con gzip y archivos tar bzip. Y hay funciones para registrar formatos de archivado de archivo adicionales (como archivos tar comprimidos xz o formatos personalizados).

Las funciones principales son make_archive() y unpack_archive(). Por defecto, ambas operan en el directorio actual (que puede ser configurado por os.chdir()) y en cualquier subdirectorio. El nombre del archivo de almacenamiento debe especificarse con una ruta completa. El paso de archivado no es destructivo (los archivos originales no se modifican).

>>> import shutil, pprint

>>> os.chdir('mydata')  # change to the source directory
>>> f = shutil.make_archive('/var/backup/mydata',
...                         'zip')      # archive the current directory
>>> f                                   # show the name of archive
'/var/backup/mydata.zip'
>>> os.chdir('tmp')                     # change to an unpacking
>>> shutil.unpack_archive('/var/backup/mydata.zip')  # recover the data

>>> pprint.pprint(shutil.get_archive_formats())  # display known formats
[('bztar', "bzip2'ed tar-file"),
 ('gztar', "gzip'ed tar-file"),
 ('tar', 'uncompressed tar file'),
 ('zip', 'ZIP file')]

>>> shutil.register_archive_format(     # register a new archive format
...     name='xz',
...     function=xz.compress,           # callable archiving function
...     extra_args=[('level', 8)],      # arguments to the function
...     description='xz compression'
... )

(Contribución de Tarek Ziadé.)

sqlite3

El módulo sqlite3 se actualizó a la versión 2.6.0 de pysqlite. Tiene dos nuevas capacidades.

(Contribución de R. David Murray y Shashwat Anand; bpo-8845.)

html

Se introdujo un nuevo módulo html con una sola función, escape(), que se usa para escapar caracteres reservados del marcado HTML:

>>> import html
>>> html.escape('x > 2 && x < 7')
'x &gt; 2 &amp;&amp; x &lt; 7'

socket

El módulo socket tiene dos nuevas mejoras.

  • Los objetos de socket ahora tienen un método detach() que pone el socket en estado cerrado sin cerrar realmente el descriptor de archivo subyacente. Este último se puede reutilizar para otros fines. (Agregado por Antoine Pitrou; bpo-8524.)

  • socket.create_connection() ahora admite el protocolo de administración de contexto para consumir incondicionalmente las excepciones socket.error y cerrar el socket cuando haya terminado. (Contribución de Giampaolo Rodolà; bpo-9794.)

ssl

El módulo ssl agregó una serie de características para satisfacer los requisitos comunes para conexiones a Internet seguras (encriptadas, autenticadas):

  • Una nueva clase, SSLContext, sirve como contenedor para datos SSL persistentes, como configuraciones de protocolo, certificados, claves privadas y varias opciones más. Incluye un wrap_socket() para crear un socket SSL a partir de un contexto SSL.

  • Una nueva función, ssl.match_hostname(), admite la verificación de identidad del servidor para protocolos de nivel superior mediante la implementación de las reglas de HTTPS (de RFC 2818) que también son adecuadas para otros protocolos.

  • La función constructora ssl.wrap_socket() ahora toma un argumento ciphers. La cadena ciphers enumera los algoritmos de cifrado permitidos utilizando el formato descrito en la documentación de OpenSSL.

  • Cuando se vincula con versiones recientes de OpenSSL, el módulo ssl ahora admite la extensión de Server Name Indication (SNI, en español: Indicador del nombre del servidor) para el protocolo TLS, lo que permite que varios» hosts virtuales «utilicen diferentes certificados en un solo puerto IP. Esta extensión solo es compatible en modo cliente y se activa pasando el argumento server_hostname a ssl.SSLContext.wrap_socket().

  • Se han agregado varias opciones al módulo ssl, como OP_NO_SSLv2 que deshabilita el protocolo SSLv2 inseguro y obsoleto.

  • La extensión ahora carga todos los algoritmos de resumen y cifrados OpenSSL. Si algunos certificados SSL no se pueden verificar, se notifican como un error de «algoritmo desconocido».

  • La versión de OpenSSL que se está utilizando ahora es accesible usando los atributos del módulo ssl.OPENSSL_VERSION (una cadena de caracteres), ssl.OPENSSL_VERSION_INFO (una tupla de 5), y ssl.OPENSSL_VERSION_NUMBER (un número entero).

(Contribución de Antoine Pitrou en bpo-8850, bpo-1589, bpo-8322, bpo-5639, bpo-4870, bpo-8484, y bpo-8321.)

nntp

El módulo nntplib tiene una implementación renovada con mejoras en la semántica de bytes y texto, así como APIs más prácticas. Estas mejoras rompen la compatibilidad con la versión nntplib en Python 3.1, que en sí misma era parcialmente disfuncional.

También se ha agregado soporte para conexiones seguras a través de TLS implícito (usando nntplib.NNTP_SSL) y explícito (usando nntplib.NNTP.starttls()).

(Contribución de Antoine Pitrou en bpo-9360 y Andrew Vant en bpo-1926.)

certificados

http.client.HTTPSConnection, urllib.request.HTTPSHandler y urllib.request.urlopen() ahora toman argumentos opcionales para permitir la comprobación del certificado del servidor con un conjunto de Autoridades de Certificación recomendado en usos públicos de HTTPS.

(Agregado por Antoine Pitrou, bpo-9003.)

imaplib

Se ha agregado soporte para TLS explícito en conexiones IMAP4 estándar a través del nuevo método imaplib.IMAP4.starttls.

(Contribución de Lorenzo M. Catucci y Antoine Pitrou, bpo-4471.)

http.client

Hubo una serie de pequeñas mejoras de API en el módulo http.client. Las respuestas simples HTTP 0.9 de estilo antiguo ya no son compatibles y el parámetro strict está obsoleto en todas las clases.

Las clases HTTPConnection y HTTPSConnection ahora tienen un parámetro source_address para una tupla (host, port) que indica desde dónde se realiza la conexión HTTP.

Se agregó soporte para verificación de certificados y hosts virtuales HTTPS a HTTPSConnection.

El método request() en los objetos de conexión permitía un argumento body opcional para que un file object pudiera usarse para proporcionar el contenido de la solicitud. Convenientemente, el argumento body ahora también acepta un objeto iterable siempre que incluya un encabezado explícito Content-Length. Esta interfaz ampliada es mucho más flexible que antes.

Para establecer una conexión HTTPS a través de un servidor proxy, existe un nuevo método set_tunnel() que establece el host y el puerto para el túnel HTTP Connect.

Para que coincida con el comportamiento de http.server, la biblioteca de cliente HTTP ahora también codifica encabezados con codificación ISO-8859-1 (Latin-1). Ya lo estaba haciendo para los encabezados entrantes, por lo que ahora el comportamiento es coherente para el tráfico entrante y saliente. (Véase el trabajo de Armin Ronacher en bpo-10980)

unittest

El módulo unittest tiene una serie de mejoras con soporte para descubrimiento de pruebas para paquetes, una experimentación más sencilla en el indicador interactivo, nuevos métodos de casos de prueba, mensajes de diagnóstico mejorados para fallas en las pruebas y mejores nombres de métodos.

  • La llamada de línea de comandos python -m unittest ahora puede aceptar rutas de archivo en lugar de nombres de módulos para ejecutar pruebas específicas (bpo-10620). El nuevo descubrimiento de pruebas puede encontrar pruebas dentro de los paquetes, localizando cualquier prueba que se pueda importar desde el directorio de nivel superior. El directorio de nivel superior se puede especificar con la opción -t, un patrón para hacer coincidir archivos con -p y un directorio para iniciar el descubrimiento con -s:

    $ python -m unittest discover -s my_proj_dir -p _test.py
    

    (Contribución de Michael Foord.)

  • La experimentación en el indicador interactivo ahora es más fácil porque la clase unittest.case.TestCase ahora se puede instanciar sin argumentos:

    >>> from unittest import TestCase
    >>> TestCase().assertEqual(pow(2, 3), 8)
    

    (Contribución de Michael Foord.)

  • El módulo unittest tiene dos métodos nuevos, assertWarns() y assertWarnsRegex() para verificar que un tipo de advertencia dado es activado por el código bajo prueba:

    with self.assertWarns(DeprecationWarning):
        legacy_function('XYZ')
    

    (Contribución de Antoine Pitrou, bpo-9754.)

    Otro método nuevo, assertCountEqual() se usa para comparar dos iterables para determinar si sus conteos de elementos son iguales (si los mismos elementos están presentes con el mismo número de ocurrencias independientemente del orden):

    def test_anagram(self):
        self.assertCountEqual('algorithm', 'logarithm')
    

    (Contribución por Raymond Hettinger.)

  • Una característica principal del módulo unittest es un esfuerzo por producir diagnósticos significativos cuando falla una prueba. Cuando es posible, la falla se registra junto con una diferencia de la salida. Esto es especialmente útil para analizar archivos de registro de ejecuciones de prueba fallidas. Sin embargo, dado que las diferencias en ocasiones pueden ser voluminosas, hay un nuevo atributo maxDiff que establece la longitud máxima de las diferencias mostradas.

  • Además, los nombres de los métodos en el módulo se han sometido a una serie de limpiezas.

    Por ejemplo, assertRegex() es el nuevo nombre de assertRegexpMatches() que fue mal nombrado porque la prueba usa re.search(), no re.match(). Otros métodos que usan expresiones regulares ahora se nombran usando la forma corta «Regex» en lugar de «Regexp» – esto coincide con los nombres usados en otras implementaciones de unittest, coincide con el nombre antiguo de Python para el módulo re, y utiliza inequívocamente camel-case.

    (Contribución de Raymond Hettinger e implementado por Ezio Melotti.)

  • Para mejorar la coherencia, algunos alias de métodos antiguos se están deprecando en favor de los nombres preferidos:

    Old Name

    Preferred Name

    assert_()

    assertTrue()

    assertEquals()

    assertEqual()

    assertNotEquals()

    assertNotEqual()

    assertAlmostEquals()

    assertAlmostEqual()

    assertNotAlmostEquals()

    assertNotAlmostEqual()

    Asimismo, se espera que los métodos TestCase.fail* obsoletos en Python 3.1 se eliminen en Python 3.3. También vea la sección Alias obsoletos en la documentación unittest.

    (Contribución de Ezio Melotti; bpo-9424.)

  • El método assertDictContainsSubset() quedó obsoleto porque porque estaba mal implementado con los argumentos en el orden incorrecto. Esto creó ilusiones ópticas difíciles de depurar en las que pruebas como TestCase().assertDictContainsSubset({'a':1, 'b':2}, {'a':1}) fallarían.

    (Contribución por Raymond Hettinger.)

random

Los métodos enteros en el módulo random ahora hacen un mejor trabajo al producir distribuciones uniformes. Anteriormente, calculaban las selecciones con int(n*random()) que tenía un ligero sesgo siempre que n no era una potencia de dos. Ahora, se realizan selecciones múltiples desde un rango hasta la siguiente potencia de dos y una selección se mantiene solo cuando cae dentro del rango 0 <= x < n. Las funciones y métodos afectados son randrange(), randint(), choice(), shuffle() y sample().

(Contribución de Raymond Hettinger; bpo-9025.)

poplib

POP3_SSL la clase ahora acepta un parámetro context, que es un objeto ssl.SSLContext que permite agrupar opciones de configuración SSL, certificados y claves privadas en una única estructura (potencialmente de larga duración) .

(Contribución de Giampaolo Rodolà; bpo-8807.)

asyncore

asyncore.dispatcher ahora proporciona un método handle_accepted() que devuelve un par (sock, addr) al que se llama cuando se ha establecido realmente una conexión con un nuevo extremo remoto. Se supone que esto se usa como reemplazo del antiguo handle_accept() y evita que el usuario llame directamente a accept().

(Contribución de Giampaolo Rodolà; bpo-6706.)

tempfile

El módulo tempfile tiene un nuevo gestor de contexto, TemporaryDirectory que proporciona una limpieza determinista fácil de directorios temporales

with tempfile.TemporaryDirectory() as tmpdirname:
    print('created temporary dir:', tmpdirname)

(Contribución de Neil Schemenauer y Nick Coghlan; bpo-5178.)

inspect

  • El módulo inspect tiene una nueva función getgeneratorstate() para identificar fácilmente el estado actual de un generador iterador:

    >>> from inspect import getgeneratorstate
    >>> def gen():
    ...     yield 'demo'
    >>> g = gen()
    >>> getgeneratorstate(g)
    'GEN_CREATED'
    >>> next(g)
    'demo'
    >>> getgeneratorstate(g)
    'GEN_SUSPENDED'
    >>> next(g, None)
    >>> getgeneratorstate(g)
    'GEN_CLOSED'
    

    (Contribución de Rodolpho Eckhardt y Nick Coghlan, bpo-10220.)

  • Para admitir búsquedas sin la posibilidad de activar un atributo dinámico, el módulo inspect tiene una nueva función, getattr_static(). A diferencia de hasattr(), esta es una verdadera búsqueda de solo lectura, garantizada que no cambiará de estado mientras está buscando:

    >>> class A:
    ...     @property
    ...     def f(self):
    ...         print('Running')
    ...         return 10
    ...
    >>> a = A()
    >>> getattr(a, 'f')
    Running
    10
    >>> inspect.getattr_static(a, 'f')
    <property object at 0x1022bd788>
    

(Contribución de Michael Foord.)

pydoc

El módulo pydoc ahora proporciona una interfaz de servidor web muy mejorada, así como una nueva opción de línea de comandos -b para abrir automáticamente una ventana del navegador para mostrar ese servidor:

$ pydoc3.2 -b

(Contribución de Ron Adam; bpo-2001.)

dis

El módulo dis obtuvo dos nuevas funciones para inspeccionar código, code_info() y show_code(). Ambas proporcionan información detallada del objeto de código para la función, método, cadena de código fuente o objeto de código suministrados. El primero retorna una cadena de caracteres y el segundo la imprime:

>>> import dis, random
>>> dis.show_code(random.choice)
Name:              choice
Filename:          /Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/random.py
Argument count:    2
Kw-only arguments: 0
Number of locals:  3
Stack size:        11
Flags:             OPTIMIZED, NEWLOCALS, NOFREE
Constants:
   0: 'Choose a random element from a non-empty sequence.'
   1: 'Cannot choose from an empty sequence'
Names:
   0: _randbelow
   1: len
   2: ValueError
   3: IndexError
Variable names:
   0: self
   1: seq
   2: i

Además, la función dis() ahora acepta argumentos de cadena para que el modismo común dis(compile(s, '', 'eval')) se pueda abreviar a dis(s):

>>> dis('3*x+1 if x%2==1 else x//2')
  1           0 LOAD_NAME                0 (x)
              3 LOAD_CONST               0 (2)
              6 BINARY_MODULO
              7 LOAD_CONST               1 (1)
             10 COMPARE_OP               2 (==)
             13 POP_JUMP_IF_FALSE       28
             16 LOAD_CONST               2 (3)
             19 LOAD_NAME                0 (x)
             22 BINARY_MULTIPLY
             23 LOAD_CONST               1 (1)
             26 BINARY_ADD
             27 RETURN_VALUE
        >>   28 LOAD_NAME                0 (x)
             31 LOAD_CONST               0 (2)
             34 BINARY_FLOOR_DIVIDE
             35 RETURN_VALUE

En conjunto, estas mejoras facilitan explorar cómo se implementa CPython y ver por sí mismo qué hace la sintaxis del lenguaje bajo el capó.

(Contribución de Nick Coghlan en bpo-9147.)

dbm

Todos los módulos de base de datos ahora admiten los métodos get() y setdefault().

(Sugerido por Ray Allen en bpo-9523.)

ctypes

Un nuevo tipo, ctypes.c_ssize_t representa el tipo de datos C ssize_t.

site

El módulo site tiene tres nuevas funciones útiles para informar sobre los detalles de una determinada instalación de Python.

  • getsitepackages() enumera todos los directorios de paquetes de sitios globales.

  • getuserbase() informa sobre el directorio base del usuario donde se pueden almacenar los datos.

  • getusersitepackages() revela la ruta del directorio de paquetes de sitio específico del usuario.

>>> import site
>>> site.getsitepackages()
['/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/site-packages',
 '/Library/Frameworks/Python.framework/Versions/3.2/lib/site-python',
 '/Library/Python/3.2/site-packages']
>>> site.getuserbase()
'/Users/raymondhettinger/Library/Python/3.2'
>>> site.getusersitepackages()
'/Users/raymondhettinger/Library/Python/3.2/lib/python/site-packages'

Convenientemente, se puede acceder a algunas de las funciones del sitio directamente desde la línea de comandos:

$ python -m site --user-base
/Users/raymondhettinger/.local
$ python -m site --user-site
/Users/raymondhettinger/.local/lib/python3.2/site-packages

(Contribución de Tarek Ziadé en bpo-6693.)

sysconfig

El nuevo módulo sysconfig hace que sea sencillo descubrir rutas de instalación y variables de configuración que varían entre plataformas e instalaciones.

El módulo ofrece acceso a funciones de acceso simple para información de plataforma y versión:

También proporciona acceso a las rutas y variables correspondientes a uno de los siete esquemas con nombre utilizados por distutils. Estos incluyen posix_prefix, posix_home, posix_user, nt, nt_user *, *os2, os2_home:

  • get_paths() crea un diccionario que contiene las rutas de instalación para el esquema de instalación actual.

  • get_config_vars() retorna un diccionario de variables específicas de la plataforma.

También hay una conveniente interfaz de línea de comandos:

C:\Python32>python -m sysconfig
Platform: "win32"
Python version: "3.2"
Current installation scheme: "nt"

Paths:
        data = "C:\Python32"
        include = "C:\Python32\Include"
        platinclude = "C:\Python32\Include"
        platlib = "C:\Python32\Lib\site-packages"
        platstdlib = "C:\Python32\Lib"
        purelib = "C:\Python32\Lib\site-packages"
        scripts = "C:\Python32\Scripts"
        stdlib = "C:\Python32\Lib"

Variables:
        BINDIR = "C:\Python32"
        BINLIBDEST = "C:\Python32\Lib"
        EXE = ".exe"
        INCLUDEPY = "C:\Python32\Include"
        LIBDEST = "C:\Python32\Lib"
        SO = ".pyd"
        VERSION = "32"
        abiflags = ""
        base = "C:\Python32"
        exec_prefix = "C:\Python32"
        platbase = "C:\Python32"
        prefix = "C:\Python32"
        projectbase = "C:\Python32"
        py_version = "3.2"
        py_version_nodot = "32"
        py_version_short = "3.2"
        srcdir = "C:\Python32"
        userbase = "C:\Documents and Settings\Raymond\Application Data\Python"

(Sacado de Distutils por Tarek Ziadé.)

pdb

El módulo depurador pdb obtuvo una serie de mejoras de usabilidad:

  • pdb.py ahora tiene una opción -c que ejecuta comandos como se indica en un archivo de script .pdbrc.

  • Un archivo de secuencia de comandos .pdbrc puede contener comandos continue y next que continúan depurando.

  • El constructor de la clase Pdb ahora acepta un argumento nosigint.

  • Nuevos comandos: l(list), ll(long list) y source para enumerar el código fuente.

  • Nuevos comandos: display y undisplay para mostrar u ocultar el valor de una expresión si ha cambiado.

  • Nuevo comando: interact para iniciar un intérprete interactivo que contiene los nombres globales y locales que se encuentran en el alcance actual.

  • Los puntos de interrupción se pueden borrar por número de punto de interrupción.

(Contribución de Georg Brandl, Antonio Cuni e Ilya Sandler.)

configparser

El módulo configparser se modificó para mejorar la usabilidad y la previsibilidad del analizador predeterminado y su sintaxis INI compatible. La antigua clase ConfigParser fue eliminada en favor de SafeConfigParser que a su vez ha sido renombrada a ConfigParser. La compatibilidad con comentarios en línea ahora está desactivada de forma predeterminada y no se permiten duplicados de secciones u opciones en una única fuente de configuración.

Los analizadores de configuración obtuvieron una nueva API basada en el protocolo de mapeo:

>>> parser = ConfigParser()
>>> parser.read_string("""
... [DEFAULT]
... location = upper left
... visible = yes
... editable = no
... color = blue
...
... [main]
... title = Main Menu
... color = green
...
... [options]
... title = Options
... """)
>>> parser['main']['color']
'green'
>>> parser['main']['editable']
'no'
>>> section = parser['options']
>>> section['title']
'Options'
>>> section['title'] = 'Options (editable: %(editable)s)'
>>> section['title']
'Options (editable: no)'

La nueva API se implementa sobre la API clásica, por lo que las subclases de analizadores personalizados deberían poder usarla sin modificaciones.

La estructura de archivos INI aceptada por los analizadores de configuración ahora se puede personalizar. Los usuarios pueden especificar opciones alternativas/delimitadores de valores y prefijos de comentarios, cambiar el nombre de la sección DEFAULT o cambiar la sintaxis de interpolación.

Hay soporte para la interpolación conectable que incluye un controlador de interpolación adicional ExtendedInterpolation:

>>> parser = ConfigParser(interpolation=ExtendedInterpolation())
>>> parser.read_dict({'buildout': {'directory': '/home/ambv/zope9'},
...                   'custom': {'prefix': '/usr/local'}})
>>> parser.read_string("""
... [buildout]
... parts =
...   zope9
...   instance
... find-links =
...   ${buildout:directory}/downloads/dist
...
... [zope9]
... recipe = plone.recipe.zope9install
... location = /opt/zope
...
... [instance]
... recipe = plone.recipe.zope9instance
... zope9-location = ${zope9:location}
... zope-conf = ${custom:prefix}/etc/zope.conf
... """)
>>> parser['buildout']['find-links']
'\n/home/ambv/zope9/downloads/dist'
>>> parser['instance']['zope-conf']
'/usr/local/etc/zope.conf'
>>> instance = parser['instance']
>>> instance['zope-conf']
'/usr/local/etc/zope.conf'
>>> instance['zope9-location']
'/opt/zope'

También se introdujeron una serie de características más pequeñas, como soporte para especificar codificación en operaciones de lectura, especificar valores de respaldo para funciones de obtención o leer directamente desde diccionarios y cadenas.

(Todos los cambios aportados por Łukasz Langa.)

urllib.parse

Se realizaron varias mejoras de usabilidad para el módulo urllib.parse.

La función urlparse() ahora admite direcciones IPv6 como se describe en RFC 2732:

>>> import urllib.parse
>>> urllib.parse.urlparse('http://[dead:beef:cafe:5417:affe:8FA3:deaf:feed]/foo/') 
ParseResult(scheme='http',
            netloc='[dead:beef:cafe:5417:affe:8FA3:deaf:feed]',
            path='/foo/',
            params='',
            query='',
            fragment='')

La función urldefrag() ahora devuelve un named tuple:

>>> r = urllib.parse.urldefrag('http://python.org/about/#target')
>>> r
DefragResult(url='http://python.org/about/', fragment='target')
>>> r[0]
'http://python.org/about/'
>>> r.fragment
'target'

Y, la función urlencode() ahora es mucho más flexible, aceptando un tipo de cadena o bytes para el argumento query. Si es una cadena, entonces los parámetros safe, encoding y error se envían a quote_plus() para codificar:

>>> urllib.parse.urlencode([
...      ('type', 'telenovela'),
...      ('name', '¿Dónde Está Elisa?')],
...      encoding='latin-1')
'type=telenovela&name=%BFD%F3nde+Est%E1+Elisa%3F'

Como se detalla en Análisis de bytes codificados ASCII, todas las funciones urllib.parse ahora aceptan cadenas de bytes codificadas en ASCII como entrada, siempre que no estén mezcladas con cadenas normales. Si se proporcionan cadenas de bytes codificadas en ASCII como parámetros, los tipos de retorno también serán cadenas de bytes codificadas en ASCII:

>>> urllib.parse.urlparse(b'http://www.python.org:80/about/') 
ParseResultBytes(scheme=b'http', netloc=b'www.python.org:80',
                 path=b'/about/', params=b'', query=b'', fragment=b'')

(Trabajo de Nick Coghlan, Dan Mahn y Senthil Kumaran en bpo-2987, bpo-5468, y bpo-9873.)

mailbox

Gracias a un esfuerzo concertado de R. David Murray, el módulo mailbox se ha corregido para Python 3.2. El desafío era que el buzón había sido diseñado originalmente con una interfaz de texto, pero los mensajes de correo electrónico se representan mejor con bytes porque varias partes de un mensaje pueden tener diferentes codificaciones.

La solución aprovechó el soporte binario de los paquete email para analizar mensajes de correo electrónico arbitrarios. Además, la solución requirió una serie de cambios en la API.

Como era de esperar, el método add() para los objetos mailbox.Mailbox ahora acepta entrada binaria.

StringIO y la entrada del archivo de texto están en desuso. Además, la entrada de cadenas fallará antes si se utilizan caracteres que no sean ASCII. Anteriormente, fallaba cuando el correo electrónico se procesaba en un paso posterior.

También hay soporte para salida binaria. El método get_file() ahora devuelve un archivo en modo binario (donde solía configurar incorrectamente el archivo en modo texto). También hay un nuevo método get_bytes() que devuelve una representación bytes de un mensaje correspondiente a una key dada.

Todavía es posible obtener una salida no binaria usando el método de la API anterior get_string(), pero ese enfoque no es muy útil. En su lugar, es mejor extraer mensajes de un objeto Message o cargarlos desde una entrada binaria.

(Contribuido por R. David Murray, con esfuerzos de Steffen Daode Nurpmeso y un parche inicial de Victor Stinner en bpo-9124.)

turtledemo

El código de demostración para el módulo turtle se movió del directorio Demo a la biblioteca principal. Incluye más de una docena de scripts de muestra con pantallas animadas. Al estar en sys.path, ahora se puede ejecutar directamente desde la línea de comandos:

$ python -m turtledemo

(Movido del directorio Demo por Alexander Belopolsky en bpo-10199.)

Multi-threading

  • Se ha reescrito el mecanismo para serializar la ejecución de subprocesos de Python que se ejecutan simultáneamente (generalmente conocido como GIL o Global Interpreter Lock). Entre los objetivos estaban los intervalos de conmutación más predecibles y la reducción de la sobrecarga debido a la contención de bloqueo y la cantidad de llamadas al sistema consiguientes. La noción de un «intervalo de verificación» para permitir cambios de hilo ha sido abandonada y reemplazada por una duración absoluta expresada en segundos. Este parámetro se puede ajustar a través de sys.setswitchinterval(). Actualmente, el valor predeterminado es 5 milisegundos.

    Se pueden leer detalles adicionales sobre la implementación en un mensaje de lista de correo python-dev mailing-list message (sin embargo, «prioridad las solicitudes» como se expone en este mensaje no se han mantenido para su inclusión).

    (Contribución de Antoine Pitrou.)

  • Los bloqueos regulares y recursivos ahora aceptan un argumento opcional timeout para su método acquire() . (Contribución de Antoine Pitrou; bpo-7316.)

  • De manera similar, threading.Semaphore.acquire() también ganó un argumento timeout. (Contribución de Torsten Landschoff; bpo-850728.)

  • Las adquisiciones de bloqueos regulares y recursivas ahora pueden ser interrumpidas por señales en plataformas que usan Pthreads. Esto significa que los programas de Python que se bloquean mientras adquieren bloqueos pueden eliminarse con éxito enviando repetidamente SIGINT al proceso (presionando Ctrl+C en la mayoría de los shells). (Contribuido por Reid Kleckner; bpo-8844.)

Optimizations

Se han agregado una serie de pequeñas mejoras de rendimiento:

  • El optimizador de mirilla de Python ahora reconoce patrones como x in {1, 2, 3} como una prueba de pertenencia a un conjunto de constantes. El optimizador reformula set como frozenset y almacena la constante preconstruida.

    Ahora que la penalización de velocidad se ha ido, es práctico comenzar a escribir pruebas de membresía usando notación de conjuntos. Este estilo es semánticamente claro y operativamente rápido:

    extension = name.rpartition('.')[2]
    if extension in {'xml', 'html', 'xhtml', 'css'}:
        handle(name)
    

    (Parche y pruebas adicionales aportadas por Dave Malcolm; bpo-6690).

  • Serializar y deserializar datos usando el módulo pickle ahora es varias veces más rápido.

    (Contribución de Alexandre Vassalotti, Antoine Pitrou y el equipo de Unladen Swallow en bpo-9410 y bpo-3873.)

  • El algoritmo Timsort algorithm usado en list.sort() y sorted() ahora se ejecuta más rápido y usa menos memoria cuando se llama con key function. Anteriormente, cada elemento de una lista se envolvía con un objeto temporal que recordaba el valor clave asociado con cada elemento. Ahora, dos matrices de claves y valores se ordenan en paralelo. Esto ahorra la memoria consumida por los contenedores de clasificación y ahorra el tiempo perdido al delegar comparaciones.

    (Parche de Daniel Stutzbach en bpo-9915.)

  • El rendimiento de la decodificación JSON mejora y el consumo de memoria se reduce siempre que se repite la misma cadena para varias claves. Además, la codificación JSON ahora usa las aceleraciones de C cuando el argumento sort_keys es verdadero.

    (Contribución de Antoine Pitrou en bpo-7451 y Raymond Hettinger y Antoine Pitrou en bpo-10314.)

  • Los bloqueos recursivos (creados con la API threading.RLock()) ahora se benefician de una implementación de C que los hace tan rápidos como los bloqueos normales, y entre 10 y 15 veces más rápidos que su anterior implementación pura de Python.

    (Contribución de Antoine Pitrou; bpo-3001.)

  • El algoritmo de búsqueda rápida en stringlib ahora es usado por los métodos split(), rsplit(), splitlines() y replace() en objetos bytes, bytearray y str. Asimismo, el algoritmo también es utilizado por rfind(), rindex(), rsplit() y rpartition().

    (Parche de Florent Xicluna en bpo-7622 y bpo-7462.)

  • Las conversiones de enteros a cadenas de caracteres ahora funcionan con dos «dígitos» a la vez, lo que reduce el número de operaciones de división y módulo.

    (bpo-6713 de Gawain Bolton, Mark Dickinson y Victor Stinner.)

Hubo varias otras optimizaciones menores. Establecer diferencias ahora se ejecuta más rápido cuando un operando es mucho más grande que el otro (parche de Andress Bennetts en bpo-8685). El método array.repeat() tiene una implementación más rápida (bpo-1569291 de Alexander Belopolsky). El BaseHTTPRequestHandler tiene un almacenamiento en búfer más eficiente (bpo-3709 por Andrew Schaaf). La función operator.attrgetter() se ha acelerado (bpo-10160 de Christos Georgiou). Y ConfigParser carga argumentos de varias líneas un poco más rápido (bpo-7113 de Łukasz Langa).

Unicode

Python se ha actualizado a Unicode 6.0.0. La actualización del estándar agrega más de 2000 caracteres nuevos, incluidos los símbolos emoji que son importantes para los teléfonos móviles.

Además, el estándar actualizado modificó las propiedades de dos caracteres de Kannada (U+0CF1, U+0CF2) y un carácter numérico New Tai Lue (U+19DA), lo que hace que el primero sea elegible para su uso en identificadores y descalifica al segundo. Para obtener más información, consulte Unicode Character Database Changes.

Codecs

Se agregó soporte para cp720 codificación DOS árabe (bpo-1616979).

La codificación MBCS ya no ignora el argumento del controlador de errores. En el modo estricto predeterminado, genera un UnicodeDecodeError cuando encuentra una secuencia de bytes no codificable y un UnicodeEncodeError para un carácter no codificable.

El códec MBCS admite los controladores de errores 'strict' e 'ignore' para la decodificación y 'strict' y 'replace' para la codificación.

Para emular la codificación Python3.1 MBCS, seleccione el controlador 'ignore' para decodificar y el controlador 'replace' para codificar.

En Mac OS X, Python decodifica los argumentos de la línea de comandos con 'utf-8' en lugar de la codificación local.

De forma predeterminada, tarfile usa la codificación 'utf-8' en Windows (en lugar de 'mbcs') y el controlador de errores 'surrogateescape' en todos los sistemas operativos.

Documentación

La documentación sigue mejorando.

  • Se ha agregado una tabla de enlaces rápidos en la parte superior de secciones largas como Funciones Built-in. En el caso de itertools, los enlaces están acompañados de tablas de resúmenes al estilo de una hoja de trucos para proporcionar una descripción general y un cambio de memoria sin tener que leer todos los documentos.

  • En algunos casos, el código fuente puro de Python puede ser un complemento útil de la documentación, por lo que ahora muchos módulos incluyen enlaces rápidos a la última versión del código fuente. Por ejemplo, la documentación del módulo functools tiene un enlace rápido en la parte superior etiquetado:

    Código fuente Lib/functools.py.

    (Contribuido por Raymond Hettinger; ver rationale.)

  • Los documentos ahora contienen más ejemplos y recetas. En particular, el módulo re tiene una sección extensa, Ejemplos de expresiones regulares. Asimismo, el módulo itertools continúa siendo actualizado con nuevo Fórmulas con itertools.

  • El módulo datetime ahora tiene una implementación auxiliar en Python puro. No se modificó ninguna funcionalidad. Esto solo proporciona una implementación alternativa más fácil de leer.

    (Contribuido por Alexander Belopolsky en bpo-9528.)

  • Se ha eliminado el directorio no mantenido Demo. Algunas demostraciones se integraron en la documentación, otras se movieron al directorio Tools/demo y otras se eliminaron por completo.

    (Contribución de Georg Brandl en bpo-7962.)

IDLE

  • El menú de formato ahora tiene una opción para limpiar archivos de origen eliminando los espacios en blanco finales.

    (Contribución de Raymond Hettinger; bpo-5150.)

  • IDLE en Mac OS X ahora funciona con Carbon AquaTk y Cocoa AquaTk.

    (Contribución de Kevin Walzer, Ned Deily y Ronald Oussoren; bpo-6075.)

Repositorio de código

Además del repositorio de código Subversion existente en https://svn.python.org, ahora hay un repositorio Mercurial en https://hg.python.org/.

Después de la versión 3.2, hay planes para cambiar a Mercurial como repositorio principal. Este sistema de control de versiones distribuido debería facilitar a los miembros de la comunidad la creación y el intercambio de conjuntos de cambios externos. Consulte PEP 385 para obtener más detalles.

Para aprender a utilizar el nuevo sistema de control de versiones, consulte el Quick Start o la Guide to Mercurial Workflows.

Cambios en la API de construcción y C

Los cambios en el proceso de compilación de Python y en la API de C incluyen:

  • Los scripts idle, pydoc y 2to3 ahora están instalados con un sufijo específico de la versión en make altinstall (bpo-10679).

  • Las funciones C que acceden a la base de datos Unicode ahora aceptan y retornan caracteres del rango Unicode completo, incluso en compilaciones Unicode estrechas (Py_UNICODE_TOLOWER, Py_UNICODE_ISDECIMAL, y otras). Una diferencia visible en Python es que unicodedata.numeric() ahora devuelve el valor correcto para puntos de código grandes y repr() puede considerar más caracteres como imprimibles.

    (Informado por Bupjoe Lee y corregido por Amaury Forgeot D’Arc; bpo-5127.)

  • Los gotos calculados ahora están habilitados de forma predeterminada en los compiladores compatibles (que son detectados por el script de configuración). Todavía se pueden desactivar de forma selectiva especificando --without-computed-gotos.

    (Contribución de Antoine Pitrou; bpo-9203.)

  • Se eliminó la opción --with-wctype-functions. La base de datos unicode incorporada ahora se usa para todas las funciones.

    (Contribución de Amaury Forgeot D’Arc; bpo-9210.)

  • Los valores hash ahora son valores de un nuevo tipo, Py_hash_t, que se define como del mismo tamaño que un puntero. Anteriormente eran del tipo long, que en algunos sistemas operativos de 64 bits todavía tiene una longitud de solo 32 bits. Como resultado de esta corrección, set y dict ahora pueden contener más de 2**32 entradas en compilaciones con punteros de 64 bits (anteriormente, podían crecer hasta ese tamaño pero su desempeño se degradaba catastróficamente).

    (Sugerido por Raymond Hettinger e implementado por Benjamin Peterson; bpo-9778.)

  • Una nueva macro Py_VA_COPY copia el estado de la lista de argumentos de la variable. Es equivalente a C99 va_copy pero está disponible en todas las plataformas Python (bpo-2443).

  • Una nueva función de la API de C PySys_SetArgvEx() permite que un intérprete integrado establezca sys.argv sin modificar también sys.path (bpo-5753).

  • PyEval_CallObject ahora solo está disponible en forma de macro. La declaración de función, que se mantuvo por razones de compatibilidad con versiones anteriores, ahora se elimina; la macro se introdujo en 1997 (bpo-8276).

  • Hay una nueva función PyLong_AsLongLongAndOverflow() que es análoga a PyLong_AsLongAndOverflow(). Ambos sirven para convertir Python int en un tipo nativo de ancho fijo al tiempo que brindan detección de casos en los que la conversión no encaja (bpo-7767).

  • La función PyUnicode_CompareWithASCIIString() ahora devuelve not equal si la cadena de Python es NUL terminada.

  • Hay una nueva función PyErr_NewExceptionWithDoc() que es como PyErr_NewException() pero permite especificar una cadena de documentos. Esto permite que las excepciones de C tengan las mismas capacidades de auto-documentación que sus contrapartes de Python puro (bpo-7033).

  • Cuando se compila con la opción --with-valgrind, el asignador de pymalloc se desactivará automáticamente cuando se ejecute en Valgrind. Esto brinda una detección mejorada de fugas de memoria cuando se ejecuta en Valgrind, mientras se aprovecha pymalloc en otros momentos (bpo-2422).

  • Se eliminó el formato O? De las funciones PyArg_Parse. El formato ya no se usa y nunca se había documentado (bpo-8837).

Hubo una serie de otros pequeños cambios en la C-API. Consulte el archivo Misc/NEWS para obtener una lista completa.

Además, hubo una serie de actualizaciones en la compilación de Mac OS X, consulte Mac/BuildScript/README.txt para obtener más detalles. Para los usuarios que ejecutan una compilación de 32/64 bits, existe un problema conocido con el Tcl/Tk predeterminado en Mac OS X 10.6. En consecuencia, recomendamos instalar una alternativa actualizada como ActiveState Tcl/Tk 8.5.9. Consulte https://www.python.org/download/mac/tcltk/ para obtener detalles adicionales.

Portar a Python 3.2

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

  • El módulo configparser tiene una serie de limpiezas. El cambio principal es reemplazar la antigua ConfigParser con la alternativa preferida de larga data SafeConfigParser. Además, hay una serie de incompatibilidades menores:

    • La sintaxis de interpolación ahora está validada en las operaciones get() y set(). En el esquema de interpolación predeterminado, solo dos tokens con signos de porcentaje son válidos: %(name)s y %%, siendo este último un signo de porcentaje de escape.

    • Los métodos set() y add_section() ahora verifican que los valores sean cadenas reales. Anteriormente, los tipos no admitidos podían introducirse involuntariamente.

    • Las secciones u opciones duplicadas de una sola fuente ahora generan DuplicateSectionError o DuplicateOptionError. Anteriormente, los duplicados sobrescribían silenciosamente una entrada anterior.

    • Los comentarios en línea ahora están deshabilitados de forma predeterminada, por lo que ahora el carácter ; se puede usar de forma segura en los valores.

    • Los comentarios ahora se pueden sangrar. En consecuencia, para que ; o # aparezcan al principio de una línea en valores multilínea, debe interpolarse. Esto evita que los caracteres de prefijo de comentario en valores se confundan con comentarios.

    • "" ahora es un valor válido y ya no se convierte automáticamente en una cadena vacía. Para cadenas vacías, use "option =" en una línea.

  • El módulo nntplib se modificó ampliamente, lo que significa que sus API a menudo son incompatibles con las API 3.1.

  • bytearray ya no se pueden usar como nombres de archivo; en su lugar, deben convertirse a bytes.

  • Los array.tostring() y array.fromstring() han sido renombrados a array.tobytes() y array.frombytes() para mayor claridad. Los nombres antiguos han quedado obsoletos. (Ver bpo-8990.)

  • Funciones PyArg_Parse*():

    • Se ha eliminado el formato «t#»: utilice «s#» o «s*» en su lugar

    • Se han eliminado los formatos «w» y «w #»: utilice «w*» en su lugar

  • El tipo PyCObject, obsoleto en 3.1, ha sido eliminado. Para envolver punteros C opacos en objetos Python, se debe utilizar la API PyCapsule; el nuevo tipo tiene una interfaz bien definida para pasar información de seguridad de escritura y una firma menos complicada para llamar a un destructor.

  • La función sys.setfilesystemencoding() se eliminó porque tenía un diseño defectuoso.

  • La función y el método random.seed() ahora saltan semillas de cadenas con una función hash sha512. Para acceder a la versión anterior de seed para reproducir secuencias de Python 3.1, establezca el argumento version en 1, random.seed(s, version=1).

  • La función anteriormente obsoleta string.maketrans() ha sido eliminada en favor de los métodos estáticos bytes.maketrans() y bytearray.maketrans(). Este cambio resuelve la confusión sobre qué tipos eran compatibles con el módulo string. Ahora, str, bytes, y bytearray cada uno tiene sus propios métodos maketrans y translate con tablas de traducción intermedias del tipo apropiado.

    (Contribución de Georg Brandl; bpo-5675.)

  • La función anteriormente obsoleta contextlib.nested() ha sido eliminada en favor de una declaración simple with que puede aceptar múltiples administradores de contexto. La última técnica es más rápida (porque está integrada) y hace un mejor trabajo finalizando múltiples administradores de contexto cuando uno de ellos genera una excepción:

    with open('mylog.txt') as infile, open('a.out', 'w') as outfile:
        for line in infile:
            if '<critical>' in line:
                outfile.write(line)
    

    (Contribución de Georg Brandl y Mattias Brändström; appspot issue 53094.)

  • struct.pack() ahora permite bytes para el código del paquete de cadenas s. Anteriormente, aceptaba argumentos de texto y los codificaba implícitamente en bytes usando UTF-8. Esto era problemático porque hacía suposiciones sobre la codificación correcta y porque una codificación de longitud variable puede fallar al escribir en un segmento de longitud fija de una estructura.

    El código como struct.pack('<6sHHBBB', 'GIF87a', x, y) debe reescribirse para usar bytes en lugar de texto, struct.pack('<6sHHBBB', b'GIF87a', x, y).

    (Descubierto por David Beazley y corregido por Victor Stinner; bpo-10783.)

  • La clase xml.etree.ElementTree ahora genera un xml.etree.ElementTree.ParseError cuando falla un análisis. Anteriormente generaba un xml.parsers.expat.ExpatError.

  • El nuevo valor más largo de str() en flotantes puede romper las pruebas de documentación que se basan en el formato de salida anterior.

  • En subprocess.Popen, el valor predeterminado para close_fds es ahora True en Unix; en Windows, es True si los tres flujos estándar están configurados como None, o False en caso contrario. Anteriormente, close_fds siempre era False de forma predeterminada, lo que producía errores difíciles de resolver o condiciones de carrera cuando los descriptores de archivos abiertos se filtraban en el proceso hijo.

  • Se ha eliminado la compatibilidad con HTTP 0.9 heredado de urllib.request y http.client. Dicho soporte todavía está presente en el lado del servidor (en http.server).

    (Contribución de Antoine Pitrou, bpo-10711.)

  • Los sockets SSL en modo de tiempo de espera ahora generan socket.timeout cuando ocurre un tiempo de espera, en lugar de un genérico SSLError.

    (Contribución de Antoine Pitrou, bpo-10272.)

  • Las funciones engañosas PyEval_AcquireLock() y PyEval_ReleaseLock() han quedado oficialmente obsoletas. Las API que reconocen el estado del hilo (como PyEval_SaveThread() y PyEval_RestoreThread()) deben usarse en su lugar.

  • Debido a riesgos de seguridad, asyncore.handle_accept() ha quedado obsoleto, y se agregó una nueva función, asyncore.handle_accepted(), para reemplazarlo.

    (Contribución de Giampaolo Rodola en bpo-6706.)

  • Debido a la nueva implementación de GIL, PyEval_InitThreads() ya no se puede llamar antes Py_Initialize().