# Qué hay de nuevo en Python 2.5

Autor:

  A.M. Kuchling

Este artículo explica las nuevas características de Python 2.5. La versión final de Python 2.5 está prevista para agosto de 2006; PEP 356 describe el cronograma de lanzamiento planificado.

Los cambios en Python 2.5 son una interesante mezcla de mejoras en el lenguaje y en las bibliotecas. Las mejoras en las bibliotecas serán más importantes para la comunidad de usuarios de Python, creo, debido a que se han añadido varios paquetes bastante útiles. Los nuevos módulos incluyen ElementTree para el procesamiento de XML (`xml.etree`), el módulo de base de datos SQLite (`sqlite`), y el módulo `ctypes` para llamar a funciones escritas en lenguaje C.

Los cambios en el lenguaje son de mediana importancia. Se han añadido algunas características nuevas y agradables, pero la mayoría de ellas no son características que vaya a utilizar todos los días. Las expresiones condicionales fueron finalmente añadidas al lenguaje usando una nueva sintaxis; ver sección PEP 308: Expresiones condicionales. La nueva sentencia “`with`” facilitará la escritura de código de limpieza (sección PEP 343: La declaración «con). Ahora se pueden pasar valores a los generadores (sección PEP 342: Nuevas funciones del generador). Las importaciones son ahora visibles como absolutas o relativas (sección PEP 328: Importaciones absolutas y relativas). Se han mejorado algunos casos de manejo de excepciones (sección PEP 341: Try/except/finally unificados). Todas estas mejoras merecen la pena, pero son mejoras de una u otra característica específica del lenguaje; ninguna de ellas es una modificación amplia de la semántica de Python.

Además de las adiciones al lenguaje y a la biblioteca, se han realizado otras mejoras y correcciones de errores en todo el árbol de código fuente. Una búsqueda en los registros de cambios del SVN revela que se aplicaron 353 parches y se corrigieron 458 errores entre Python 2.4 y 2.5. (Es probable que ambas cifras estén subestimadas)

Este artículo no pretende ser una especificación completa de las nuevas características; en su lugar, los cambios se introducen brevemente utilizando ejemplos útiles. Para obtener todos los detalles, siempre debes consultar la documentación de Python 2.5 en https://docs.python.org. Si quieres entender la implementación completa y los fundamentos del diseño, consulta el PEP de una nueva característica en particular.

Son bienvenidos los comentarios, las sugerencias y los informes de errores para este documento; por favor, envíelos por correo electrónico al autor o abra un error en el rastreador de errores de Python.

## PEP 308: Expresiones condicionales

Durante mucho tiempo, la gente ha solicitado una forma de escribir expresiones condicionales, que son expresiones que devuelven el valor A o el valor B dependiendo de si un valor booleano es verdadero o falso. Una expresión condicional le permite escribir una única sentencia de asignación que tiene el mismo efecto que la siguiente:

    Si la condición es:
    x = valor_verdadero
    De lo contrario:
    x = valor_falso

Ha habido interminables y tediosas discusiones sobre la sintaxis tanto en python-dev como en comp.lang.python. Incluso se llevó a cabo una votación en la que se descubrió que la mayoría de los votantes querían expresiones condicionales de alguna forma, pero no había ninguna sintaxis que fuera preferida por una clara mayoría. Los candidatos incluían `cond ? true_v : false_v`, `if cond then true_v else false_v`, y otras 16 variaciones.

Guido van Rossum eligió finalmente una sintaxis sorprendente:

    x = valor_verdadero si condición de lo contrario valor_falso

La evaluación sigue siendo perezosa como en las expresiones booleanas existentes, por lo que el orden de evaluación salta un poco. La expresión condición del medio se evalúa primero, y la expresión valor_verdadero se evalúa sólo si la condición es verdadera. Del mismo modo, la expresión valor_falso sólo se evalúa cuando la condición es falsa.

Esta sintaxis puede parecer extraña y retrógrada; ¿por qué la condición va en el medio de la expresión, y no en la parte delantera como en `c ? x : y` de C? La decisión se comprobó aplicando la nueva sintaxis a los módulos de la biblioteca estándar y viendo cómo se leía el código resultante. En muchos casos en los que se utiliza una expresión condicional, un valor parece ser el «caso común» y otro valor es un «caso excepcional», utilizado sólo en las raras ocasiones en las que no se cumple la condición. La sintaxis condicional hace que este patrón sea un poco más obvio:

    contenido = ((doc + '\n') si doc si no '')

Leo la afirmación anterior en el sentido de que «aquí se asigna a contents un valor de `doc+'\n'`; a veces doc está vacío, en cuyo caso especial se devuelve una cadena vacía» Dudo que use expresiones condicionales muy a menudo donde no hay un caso común y no común claro.

Hubo alguna discusión sobre si el lenguaje debería requerir rodear las expresiones condicionales con paréntesis. Se tomó la decisión de no requerir paréntesis en la gramática del lenguaje Python, pero como una cuestión de estilo creo que siempre deberías usarlos. Considere estas dos declaraciones:

    # Primera versión: sin paréntesis
    nivel = 1 si se registra, de lo contrario, 0

    # Segunda versión: con paréntesis
    nivel = (1 si se registra, de lo contrario, 0)

En la primera versión, creo que el ojo de un lector podría agrupar la sentencia en “nivel = 1”, “si registro”, “si no 0”, y pensar que la condición decide si se realiza la asignación a nivel. La segunda versión se lee mejor, en mi opinión, porque deja claro que la asignación se realiza siempre y que se está eligiendo entre dos valores.

Otra razón para incluir los paréntesis: algunas combinaciones extrañas de comprensiones de listas y lambdas podrían parecer expresiones condicionales incorrectas. Véase PEP 308 para algunos ejemplos. Si pone paréntesis alrededor de sus expresiones condicionales, no se encontrará con este caso.

Ver también

PEP 308 - Expresiones condicionales

  PEP escrito por Guido van Rossum y Raymond D. Hettinger; implementado por Thomas Wouters.

## PEP 309: Aplicación parcial de funciones

El módulo `functools` está destinado a contener herramientas para la programación de estilo funcional.

Una herramienta útil de este módulo es la función `partial()`. Para los programas escritos en un estilo funcional, a veces querrá construir variantes de funciones existentes que tengan algunos de los parámetros rellenados. Considere una función Python `f(a, b, c)`; podría crear una nueva función `g(b, c)` que fuera equivalente a `f(1, b, c)`. Esto se llama «aplicación parcial de funciones».

`parcial()` toma los argumentos `(function, arg1, arg2, ... kwarg1=valor1, kwarg2=valor2)`. El objeto resultante es invocable, por lo que puedes llamarlo para invocar la función con los argumentos rellenados.

He aquí un pequeño pero realista ejemplo:

    import functools

    def log (message, subsystem):
    "Escribe el contenido de 'message' en el subsistema especificado".
    print '%s: %s' % (subsystem, message)
    ...

    server_log = functools.partial(log, subsystem='server')
    server_log('No se puede abrir el socket')

Aquí hay otro ejemplo, de un programa que utiliza PyGTK. Aquí se está construyendo dinámicamente un menú emergente sensible al contexto. El callback proporcionado para la opción de menú es una versión parcialmente aplicada del método `open_item()`, donde se ha proporcionado el primer argumento

    ...
    class Application:
        def open_item(self, path):
           ...
        def init (self):
            open_func = functools.partial(self.open_item, item_path)
            popup_menu.append( ("Open", open_func, 1) )

Otra función del módulo `functools` es la función `update_wrapper(wrapper, wrapped)` que le ayuda a escribir decoradores con un buen comportamiento. `update_wrapper()` copia el nombre, el módulo y el atributo docstring a una función wrapper para que las trazas dentro de la función envuelta sean más fáciles de entender. Por ejemplo, puedes escribir:

    def my_decorator(f):
        def wrapper(*args, **kwds):
            print 'Calling decorated function'
            return f(*args, **kwds)
        functools.update_wrapper(wrapper, f)
        return wrapper

`wraps()` es un decorador que se puede utilizar dentro de sus propios decoradores para copiar la información de la función envuelta. Una versión alternativa del ejemplo anterior sería:

    def my_decorator(f):
        @functools.wraps(f)
        def wrapper(*args, **kwds):
            print 'Calling decorated function'
            return f(*args, **kwds)
        return wrapper

Ver también

PEP 309 - Aplicación parcial de funciones

  PEP propuesto y escrito por Peter Harris; implementado por Hye-Shik Chang y Nick Coghlan, con adaptaciones de Raymond Hettinger.

## PEP 314: Metadatos para paquetes de software Python v1.1

Se ha añadido a Distutils un sencillo soporte de dependencias. La función `setup()` ahora tiene parámetros de palabras clave `requires`, `provides` y `obsoletes`. Cuando se construye una distribución de origen utilizando el comando `sdist`, la información de las dependencias se registrará en el archivo `PKG-INFO`.

Otro nuevo parámetro de palabra clave es `download_url`, que debe establecerse como una URL para el código fuente del paquete. Esto significa que ahora es posible buscar una entrada en el índice de paquetes, determinar las dependencias de un paquete y descargar los paquetes necesarios.

    VERSION = '1.0'
    setup(name='PyPackage',
          version=VERSION,
          requires=['numarray', 'zlib (>=1.1.4)'],
          obsoletes=['OldPackage']
          download_url=('http://www.example.com/pypackage/dist/pkg-%s.tar.gz'
                        % VERSION),
         )

Otra nueva mejora en el índice de paquetes de Python en https://pypi.org es el almacenamiento de archivos fuente y binarios de un paquete. El nuevo comando upload de Distutils subirá un paquete al repositorio.

Antes de poder subir un paquete, debes ser capaz de construir una distribución usando el comando sdist de Distutils. Una vez que funcione, puedes ejecutar `python setup.py upload` para añadir tu paquete al archivo PyPI. Opcionalmente puedes firmar el paquete con GPG suministrando las opciones `--sign` y `--identity`.

La carga de paquetes fue implementada por Martin von Löwis y Richard Jones.

Ver también

PEP 314 - Metadatos para paquetes de software Python v1.1

  PEP propuesto y redactado por A.M. Kuchling, Richard Jones y Fred Drake; aplicado por Richard Jones y Fred Drake.

## PEP 328: Importaciones absolutas y relativas

La parte más sencilla de PEP 328 se implementó en Python 2.4: los paréntesis podían utilizarse ahora para encerrar los nombres importados de un módulo utilizando la sentencia `from ... import ...`, facilitando la importación de muchos nombres diferentes.

La parte más complicada se ha implementado en Python 2.5: la importación de un módulo puede especificarse para utilizar importaciones absolutas o relativas al paquete. El plan es hacer que las importaciones absolutas sean el valor por defecto en futuras versiones de Python.

Digamos que tienes un directorio de paquetes como este:

    pkg/
    pkg/__init__.py
    pkg/main.py
    pkg/string.py

Esto define un paquete llamado `pkg` que contiene los submódulos `pkg.main` y `pkg.string`.

Considera el código del módulo `main.py`. ¿Qué ocurre si ejecuta la sentencia `importar cadena`? En Python 2.4 y anteriores, primero buscará en el directorio del paquete para realizar una importación relativa, encuentra `pkg/string.py`, importa el contenido de ese archivo como el módulo `pkg.string`, y ese módulo se vincula al nombre `string` en el espacio de nombres del módulo `pkg.main`.

Eso está bien si `pkg.string` era lo que querías. ¿Pero qué pasa si quieres el módulo estándar de Python `string`? No hay una forma limpia de ignorar `pkg.string` y buscar el módulo estándar; generalmente tienes que mirar el contenido de `sys.modules`, lo cual es ligeramente sucio. El paquete `py.std` de Holger Krekel proporciona una forma más ordenada de realizar importaciones desde la biblioteca estándar, `import py; py.std.string.join()`, pero ese paquete no está disponible en todas las instalaciones de Python.

La lectura de código que depende de importaciones relativas también es menos clara, porque un lector puede confundirse sobre qué módulo, `cadena` o `cadena.pkg`, se pretende utilizar. Los usuarios de Python aprendieron pronto a no duplicar los nombres de los módulos de la biblioteca estándar en los nombres de los submódulos de sus paquetes, pero no puedes protegerte de que el nombre de tu submódulo se utilice para un nuevo módulo añadido en una futura versión de Python.

En Python 2.5, puedes cambiar el comportamiento de `import` a importaciones absolutas usando una directiva `from __future__ import absolute_import`. Este comportamiento de importación absoluta será el predeterminado en una versión futura (probablemente Python 2.7). Una vez que las importaciones absolutas sean el valor por defecto, `import string` siempre encontrará la versión de la biblioteca estándar. Se sugiere que los usuarios comiencen a usar importaciones absolutas tanto como sea posible, así que es preferible comenzar a escribir `de pkg import string` en su código.

Las importaciones relativas siguen siendo posibles añadiendo un punto inicial al nombre del módulo cuando se utiliza la forma `from ... import`:

    # Import names from pkg.string
    from .string import name1, name2
    # Import pkg.string
    from . import string

Esto importa el módulo `string` relativo al paquete actual, así que en `pkg.main` esto importará nombre1 y nombre2 de `pkg.string`. Los puntos iniciales adicionales realizan la importación relativa empezando por el padre del paquete actual. Por ejemplo, el código en el módulo `A.B.C` puede hacer:

    from . import D                 # Imports A.B.D
    from .. import E                # Imports A.E
    from ..F import G               # Imports A.F.G

Los puntos suspensivos no pueden usarse con la forma `importar nombre de modelo` de la sentencia import, sólo con la forma `de ... import`.

Ver también

PEP 328 - Importaciones: Multilínea y Absoluto/Relativo

  PEP escrito por Aahz; implementado por Thomas Wouters.

https://pylib.readthedocs.io/

  La biblioteca py de Holger Krekel, que contiene el paquete `py.std`.

## PEP 338: Ejecutando Módulos como Scripts

El conmutador `-m` añadido en Python 2.4 para ejecutar un módulo como un script ganó algunas habilidades más. En lugar de estar implementado en código C dentro del intérprete de Python, el interruptor ahora utiliza una implementación en un nuevo módulo, `runpy`.

El módulo `runpy` implementa un mecanismo de importación más sofisticado de forma que ahora es posible ejecutar módulos en un paquete como `pychecker.checker`. El módulo también soporta mecanismos de importación alternativos como el módulo `zipimport`. Esto significa que puede añadir la ruta de un archivo .zip a `sys.path` y luego utilizar el modificador `-m` para ejecutar el código del archivo.

Ver también

PEP 338 - Ejecución de módulos como scripts

  PEP escrito e implementado por Nick Coghlan.

## PEP 341: Try/except/finally unificados

Hasta la versión 2.5 de Python, la sentencia `try` tenía dos variantes. Podías usar un bloque `finally` para asegurarte de que el código se ejecutaba siempre, o uno o más bloques `except` para capturar excepciones específicas. No podías combinar ambos bloques `except` y un bloque `finally`, porque generar el bytecode correcto para la versión combinada era complicado y no estaba claro cuál debía ser la semántica de la sentencia combinada.

Guido van Rossum pasó algún tiempo trabajando con Java, que sí soporta el equivalente de combinar bloques `except` y un bloque `finally`, y esto aclaró lo que debería significar la declaración. En Python 2.5, ahora se puede escribir:

    try:
        block-1 ...
    except Exception1:
        handler-1 ...
    except Exception2:
        handler-2 ...
    else:
        else-block
    finally:
        final-block

Se ejecuta el código del bloque-1. Si el código lanza una excepción, se comprueban los distintos bloques `except`: si la excepción es de clase `Exception1`, se ejecuta handler-1; en caso contrario, si es de clase `Exception2`, se ejecuta handler-2, y así sucesivamente. Si no se produce ninguna excepción, se ejecuta el bloque else.

No importa lo que haya sucedido previamente, el bloque final se ejecuta una vez que el bloque de código se ha completado y se han manejado las excepciones planteadas. Incluso si hay un error en un manejador de excepciones o en el bloque else y se lanza una nueva excepción, el código del bloque final se sigue ejecutando.

Ver también

PEP 341 - Unificar try-except y try-finally

  PEP escrito por Georg Brandl; implementación por Thomas Lee.

## PEP 342: Nuevas funciones del generador

Python 2.5 añade una forma sencilla de pasar valores a un generador. Tal y como se introdujo en Python 2.3, los generadores sólo producen salida; una vez que se invoca el código de un generador para crear un iterador, no hay forma de pasar ninguna información nueva a la función cuando se reanuda su ejecución. A veces, la capacidad de pasar alguna información sería útil. Las soluciones más ingeniosas para esto incluyen hacer que el código del generador mire a una variable global y luego cambie el valor de la variable global, o pasar algún objeto mutable que los llamadores luego modifiquen.

Para refrescar la memoria de los generadores básicos, he aquí un ejemplo sencillo:

    def counter (maximum):
        i = 0
        while i < maximum:
            yield i
            i += 1

Cuando se llama a `contador(10)`, el resultado es un iterador que devuelve los valores de 0 a 9. Al encontrar la sentencia `yield`, el iterador devuelve el valor proporcionado y suspende la ejecución de la función, preservando las variables locales. La ejecución se reanuda en la siguiente llamada al método `next()` del iterador, retomando después de la sentencia `yield`.

En Python 2.3, `yield` era una declaración; no devolvía ningún valor. En 2.5, `yield` es ahora una expresión, que devuelve un valor que se puede asignar a una variable o que se puede operar de otra manera:

    val = (rendimiento i)

Te recomiendo que siempre pongas paréntesis alrededor de una expresión `yield` cuando estés haciendo algo con el valor devuelto, como en el ejemplo anterior. Los paréntesis no siempre son necesarios, pero es más fácil añadirlos siempre en lugar de tener que recordar cuándo son necesarios.

(PEP 342 explica las reglas exactas, que consisten en que una expresión `yield`debe ir siempre entre paréntesis, excepto cuando ocurre en la expresión de nivel superior en el lado derecho de una asignación. Esto significa que puedes escribir `val = yield i` pero tienes que usar paréntesis cuando hay una operación, como en `val = (yield i) + 12`)

Los valores se envían a un generador llamando a su método `send(value)`. El código del generador se reanuda y la expresión `yield` devuelve el valor especificado. Si se llama al método regular `next()`, la expresión `yield` devuelve `None`.

Aquí está el ejemplo anterior, modificado para permitir cambiar el valor del contador interno.

    def counter (maximum):
        i = 0
        while i < maximum:
            val = (yield i)
            # If value provided, change counter
            if val is not None:
                i = val
            else:
                i += 1

Y aquí hay un ejemplo de cambio de contador:

    >>> it = counter(10)
    >>> print it.next()
    0
    >>> print it.next()
    1
    >>> print it.send(8)
    8
    >>> print it.next()
    9
    >>> print it.next()
    Traceback (most recent call last):
      File "t.py", line 15, in ?
        print it.next()
    StopIteration

`yield` normalmente devolverá `None`, por lo que siempre debes comprobar este caso. No utilices su valor en las expresiones sin más, a menos que estés seguro de que el método `send()` será el único utilizado para reanudar tu función generadora.

Además de `send()`, hay otros dos nuevos métodos en los generadores:

- `throw(type, value=None, traceback=None)` se utiliza para lanzar una excepción dentro del generador; la excepción es lanzada por la expresión `yield` donde la ejecución del generador se pausa.

- `close()` lanza una nueva excepción `GeneratorExit` dentro del generador para terminar la iteración. Al recibir esta excepción, el código del generador debe lanzar `GeneratorExit` o `StopIteration`. Capturar la excepción `GeneratorExit` y devolver un valor es ilegal y provocará un `RuntimeError`; si la función lanza alguna otra excepción, esa excepción se propaga a quien la llama. `close()` también será llamado por el recolector de basura de Python cuando el generador sea recolectado.

  Si necesitas ejecutar código de limpieza cuando se produce un `GeneratorExit`, te sugiero que utilices un conjunto `try: ... finally:` en lugar de atrapar `GeneratorExit`.

El efecto acumulativo de estos cambios es que los generadores pasan de ser productores unidireccionales de información a ser tanto productores como consumidores.

Los generadores también se convierten en corutinas, una forma más generalizada de subrutinas. Las subrutinas se introducen en un punto y se salen en otro (la parte superior de la función, y una declaración `return`), pero las coroutines pueden introducirse, salirse y reanudarse en muchos puntos diferentes (las declaraciones `yield`). Tendremos que descubrir patrones para usar coroutines de forma efectiva en Python.

La adición del método `close()` tiene un efecto secundario que no es obvio. `close()` es llamado cuando un generador es recogido por la basura, lo que significa que el código del generador tiene una última oportunidad de ejecutarse antes de que el generador sea destruido. Esta última oportunidad significa que ahora se puede garantizar que las sentencias `intentar...finalmente` en los generadores funcionen; la cláusula `finally` ahora siempre tendrá una oportunidad de ejecutarse. Por lo tanto, se ha eliminado la restricción sintáctica que impedía mezclar sentencias `yield` con un conjunto `try...finally`. Esto parece una trivialidad menor del lenguaje, pero el uso de generadores y `try...finally` es realmente necesario para implementar la sentencia `with` descrita por PEP 343. Veré esta nueva sentencia en la siguiente sección.

Otro efecto aún más esotérico de este cambio: antes, el atributo `gi_frame` de un generador era siempre un objeto frame. Ahora es posible que `gi_frame` sea `None` una vez que el generador se ha agotado.

Ver también

PEP 342 - Coroutines mediante generadores mejorados

  PEP escrito por Guido van Rossum y Phillip J. Eby; implementado por Phillip J. Eby. Incluye ejemplos de algunos usos más sofisticados de los generadores como coroutines.

  Versiones anteriores de estas características fueron propuestas en PEP 288 por Raymond Hettinger y PEP 325 por Samuele Pedroni.

https://en.wikipedia.org/wiki/Coroutine

  La entrada de Wikipedia para las coroutines.

https://web.archive.org/web/20160321211320/http://www.sidhe.org/~dan/blog/archives/000178.html

  Una explicación de las coroutines desde el punto de vista de Perl, escrita por Dan Sugalski.

## PEP 343: La declaración «con

La sentencia “`with`” aclara el código que antes utilizaba bloques `try...finally`” para asegurar que se ejecuta el código de limpieza. En esta sección, hablaré de la sentencia tal y como se utiliza habitualmente. En la siguiente sección, examinaré los detalles de la implementación y mostraré cómo escribir objetos para usar con esta sentencia.

La declaración “`with`” es una nueva estructura de flujo de control cuya estructura básica es:

    with expression [as variable]:
        with-block

Se evalúa la expresión y debería dar como resultado un objeto que admita el protocolo de gestión de contexto (es decir, que tenga los métodos `__enter__()` y `__exit__()`).

El objeto `__enter__()` se llama antes de que se ejecute with-block y, por lo tanto, puede ejecutar el código de configuración. También puede devolver un valor vinculado al nombre variable, si se proporciona. (Tenga en cuenta que variable es not al que se le asigna el resultado de expression).

Una vez finalizada la ejecución de with-block, se llama al método `__exit__()` del objeto, incluso si el bloque generó una excepción y, por lo tanto, puede ejecutar código de limpieza.

Para habilitar la declaración en Python 2.5, debe añadir la siguiente directiva a su módulo:

    desde __future__ importar con_declaración

La declaración siempre estará habilitada en Python 2.6.

Algunos objetos estándar de Python soportan ahora el protocolo de gestión de contextos y pueden utilizarse con la sentencia “`with`””. Los objetos de archivo son un ejemplo:

    with open('/etc/passwd', 'r') as f:
        for line in f:
            print line
            ... more processing code ...

Después de que esta sentencia se haya ejecutado, el objeto archivo en f se habrá cerrado automáticamente, incluso si el bucle `for` lanzó una excepción a mitad del bloque.

Nota

En este caso, f es el mismo objeto creado por `open()`, porque `__enter__()` devuelve self.

Los bloqueos y las variables de condición del módulo `threading` también soportan la sentencia “`with`”:

    lock = threading.Lock()
    with lock:
        # Critical section of code
        ...

El bloqueo se adquiere antes de que se ejecute el bloque y siempre se libera una vez que el bloque se ha completado.

La nueva función `localcontext()` del módulo `decimal` facilita el guardado y la restauración del contexto decimal actual, que encapsula las características de precisión y redondeo deseadas para los cálculos:

    from decimal import Decimal, Context, localcontext

    # Displays with default precision of 28 digits
    v = Decimal('578')
    print v.sqrt()

    with localcontext(Context(prec=16)):
        # All code in this block uses a precision of 16 digits.
        # The original context is restored on exiting the block.
        print v.sqrt()

### Redacción de Gestores de Contexto

Bajo el capó, la sentencia “`with`” es bastante complicada. La mayoría de la gente sólo utilizará “`with`” en compañía de objetos existentes y no necesita conocer estos detalles, así que puedes saltarte el resto de esta sección si quieres. Los autores de nuevos objetos necesitarán entender los detalles de la implementación subyacente y deberían seguir leyendo.

Una explicación de alto nivel del protocolo de gestión del contexto es:

- La expresión se evalúa y debería generar un objeto denominado «administrador de contexto». El administrador de contexto debe tener los métodos `__enter__()` y `__exit__()`.

- Se llama al método `__enter__()` del administrador de contexto. El valor devuelto se asigna a VAR. Si no hay ninguna cláusula `'as VAR'`, el valor simplemente se descarta.

- Se ejecuta el código en BLOQUE.

- Si BLOCK lanza una excepción, se llama a `__exit__(type, value, traceback)` con los detalles de la excepción, los mismos valores devueltos por `sys.exc_info()`. El valor de retorno del método controla si la excepción se vuelve a lanzar: cualquier valor falso vuelve a lanzar la excepción, y `True` resultará en suprimirla. Sólo en raras ocasiones querrá suprimir la excepción, porque si lo hace el autor del código que contiene la declaración “`with`” nunca se dará cuenta de que algo ha ido mal.

- Si BLOCK no generó una excepción, aún se llama al método `__exit__()`, pero type, value y traceback son todos `None`.

Pensemos en un ejemplo. No presentaré un código detallado, sino que sólo esbozaré los métodos necesarios para una base de datos que soporte transacciones.

(Para quienes no estén familiarizados con la terminología de las bases de datos: un conjunto de cambios en la base de datos se agrupa en una transacción. Las transacciones pueden ser confirmadas, lo que significa que todos los cambios se escriben en la base de datos, o revertidas, lo que significa que todos los cambios se descartan y la base de datos no se modifica. Consulte cualquier libro de texto sobre bases de datos para obtener más información)

Supongamos que hay un objeto que representa una conexión a la base de datos. Nuestro objetivo será permitir que el usuario escriba código como este:

    db_connection = DatabaseConnection()
    with db_connection as cursor:
        cursor.execute('insert into ...')
        cursor.execute('delete from ...')
        # ... more operations ...

La transacción debe ser confirmada si el código en el bloque se ejecuta sin problemas o revertida si hay una excepción. Aquí está la interfaz básica para `DatabaseConnection` que voy a asumir:

    class DatabaseConnection:
        # Database interface
        def cursor (self):
            "Returns a cursor object and starts a new transaction"
        def commit (self):
            "Commits current transaction"
        def rollback (self):
            "Rolls back current transaction"

El método `__enter__()` es bastante sencillo, ya que solo hay que iniciar una nueva transacción. Para esta aplicación, el objeto cursor resultante sería un resultado útil, por lo que el método lo devolverá. El usuario puede entonces añadir `as cursor` a su declaración “`with`” para vincular el cursor a un nombre de variable.

    class DatabaseConnection:
        ...
        def __enter__ (self):
            # Code to start a new transaction
            cursor = self.cursor()
            return cursor

El método `__exit__()` es el más complicado porque es donde se debe realizar la mayor parte del trabajo. El método debe verificar si se produjo una excepción. Si no hubo excepción, se confirma la transacción. Si hubo una excepción, se revierte la transacción.

En el código de abajo, la ejecución simplemente caerá al final de la función, devolviendo el valor por defecto de `None`. `None` es falso, por lo que la excepción se volverá a lanzar automáticamente. Si lo desea, puede ser más explícito y añadir una declaración `return` en el lugar marcado.

    class DatabaseConnection:
        ...
        def __exit__ (self, type, value, tb):
            if tb is None:
                # No exception, so commit
                self.commit()
            else:
                # Exception occurred, so rollback.
                self.rollback()
                # return False

### El módulo contextlib

El nuevo módulo `contextlib` proporciona algunas funciones y un decorador que son útiles para escribir objetos para usar con la sentencia “`with`”.

El decorador se llama `contextmanager()` y le permite escribir una única función generadora en lugar de definir una nueva clase. El generador debería generar exactamente un valor. El código hasta `yield` se ejecutará como el método `__enter__()` y el valor generado será el valor de retorno del método que se vinculará a la variable en la cláusula `as` de la declaración “`with`”, si la hay. El código después de `yield` se ejecutará en el método `__exit__()`. Cualquier excepción generada en el bloque será generada por la declaración `yield`.

Nuestro ejemplo de base de datos de la sección anterior podría escribirse utilizando este decorador como:

    from contextlib import contextmanager

    @contextmanager
    def db_transaction (connection):
        cursor = connection.cursor()
        try:
            yield cursor
        except:
            connection.rollback()
            raise
        else:
            connection.commit()

    db = DatabaseConnection()
    with db_transaction(db) as cursor:
        ...

El módulo `contextlib` también tiene una función `anidada(mgr1, mgr2, ...)` que combina varios gestores de contexto para que no sea necesario escribir sentencias “`with`” anidadas. En este ejemplo, la única sentencia “`with`` inicia una transacción de base de datos y adquiere un bloqueo de hilo:

    lock = threading.Lock()
    con anidado (db_transaction(db), lock) como (cursor, bloqueado):
    ...

Por último, la función `closing(object)` devuelve el objeto para que pueda ser vinculado a una variable, y llama a `object.close` al final del bloque.

    import urllib, sys
    from contextlib import closing

    with closing(urllib.urlopen('http://www.yahoo.com')) as f:
        for line in f:
            sys.stdout.write(line)

Ver también

PEP 343 - La declaración «con»

  PEP escrito por Guido van Rossum y Nick Coghlan; implementado por Mike Bland, Guido van Rossum y Neal Norwitz. El PEP muestra el código generado para una sentencia “`with`”, que puede ser útil para aprender cómo funciona la sentencia.

La documentación del módulo `contextlib`.

## PEP 352: Las excepciones como clases de nuevo estilo

Las clases de excepción ahora pueden ser clases de nuevo estilo, no sólo clases clásicas, y la clase incorporada `Exception` y todas las excepciones incorporadas estándar (`NameError`, `ValueError`, etc.) son ahora clases de nuevo estilo.

La jerarquía de herencia de las excepciones se ha reordenado un poco. En 2.5, las relaciones de herencia son:

    BaseException       # New in Python 2.5
    |- KeyboardInterrupt
    |- SystemExit
    |- Exception
       |- (all other current built-in exceptions)

Esta reorganización se hizo porque la gente a menudo quiere atrapar todas las excepciones que indican errores del programa. `KeyboardInterrupt` y `SystemExit` no son errores, sin embargo, y por lo general representan una acción explícita como el usuario pulsando `Control`-`C` o el código llamando a `sys.exit()`. Una simple `except:` atrapará todas las excepciones, por lo que comúnmente se necesita listar `KeyboardInterrupt` y `SystemExit` para volver a lanzarlas. El patrón habitual es:

    try:
        ...
    except (KeyboardInterrupt, SystemExit):
        raise
    except:
        # Log error...
        # Continue running program...

En Python 2.5, ahora puedes escribir `except Exception` para conseguir el mismo resultado, capturando todas las excepciones que suelen indicar errores pero dejando `KeyboardInterrupt` y `SystemExit` en paz. Como en versiones anteriores, un `except:` desnudo sigue capturando todas las excepciones.

El objetivo de Python 3.0 es requerir que cualquier clase lanzada como excepción derive de `BaseException` o de algún descendiente de `BaseException`, y las futuras versiones de la serie Python 2.x pueden empezar a imponer esta restricción. Por lo tanto, sugiero que empieces a hacer que todas tus clases de excepción deriven de `Exception` ahora. Se ha sugerido que la forma desnuda `except:` sea eliminada en Python 3.0, pero Guido van Rossum no ha decidido si hacerlo o no.

El lanzamiento de cadenas como excepciones, como en la declaración `raise "Error occurred"`, está obsoleto en Python 2.5 y provocará una advertencia. El objetivo es poder eliminar la función de excepción de cadena en algunas versiones.

Ver también

PEP 352 - Superclase necesaria para las excepciones

  PEP escrito por Brett Cannon y Guido van Rossum; implementado por Brett Cannon.

## PEP 353: Uso de ssize_t como tipo de índice

Un cambio de gran alcance en la API C de Python, que usa una nueva definición de tipo `Py_ssize_t` en lugar de int, permitirá que el intérprete maneje más datos en plataformas de 64 bits. Este cambio no afecta la capacidad de Python en plataformas de 32 bits.

Varias piezas del intérprete de Python usaban el tipo int de C para almacenar tamaños o conteos; por ejemplo, la cantidad de elementos en una lista o tupla se almacenaron en un int. Los compiladores de C para la mayoría de las plataformas de 64 bits aún definen int como un tipo de 32 bits, lo que significa que las listas solo pueden contener hasta `2**31 - 1` = 2147483647 elementos. (En realidad, hay algunos modelos de programación diferentes que los compiladores de C de 64 bits pueden usar; consulte https://unix.org/version2/whatsnew/lp64_wp.html para ver una discusión, pero el modelo más comúnmente disponible deja int como 32 bits).

Un límite de 2147483647 elementos no importa realmente en una plataforma de 32 bits porque te quedarás sin memoria antes de alcanzar el límite de longitud. Cada elemento de la lista requiere espacio para un puntero, que es de 4 bytes, más espacio para un `PyObject` que representa el elemento. 2147483647*4 ya son más bytes de los que puede contener un espacio de direcciones de 32 bits.

Sin embargo, es posible abordar esa cantidad de memoria en una plataforma de 64 bits. Los punteros para una lista de ese tamaño solo requerirían 16 GiB de espacio, por lo que no es irrazonable que los programadores de Python puedan construir listas tan grandes. Por lo tanto, el intérprete de Python tuvo que cambiarse para usar algún tipo diferente a int, y este será un tipo de 64 bits en plataformas de 64 bits. El cambio provocará incompatibilidades en las máquinas de 64 bits, por lo que se consideró que valía la pena hacer la transición ahora, mientras que la cantidad de usuarios de 64 bits aún es relativamente pequeña. (En 5 o 10 años, es posible que todo esté en máquinas de 64 bits y la transición sería más dolorosa entonces).

Este cambio afecta en mayor medida a los autores de módulos de extensión de C. Las cadenas de Python y los tipos contenedores como las listas y las tuplas utilizan ahora `Py_ssize_t` para almacenar su tamaño. Funciones como `PyList_Size()` ahora devuelven `Py_ssize_t`. Por lo tanto, el código de los módulos de extensión puede necesitar cambiar algunas variables a `Py_ssize_t`.

Las funciones `PyArg_ParseTuple()` y `Py_BuildValue()` tienen un nuevo código de conversión, `n`, para `Py_ssize_t`. `s#` y `t#` de `PyArg_ParseTuple()` aún generan int de forma predeterminada, pero puede definir la macro `PY_SSIZE_T_CLEAN` antes de incluir `Python.h` para que devuelvan `Py_ssize_t`.

PEP 353 tiene una sección sobre directrices de conversión que los autores de extensiones deberían leer para aprender a soportar plataformas de 64 bits.

Ver también

PEP 353 - Uso de ssize_t como tipo de índice

  PEP escrito y aplicado por Martin von Löwis.

## PEP 357: El método “__index__”

Los desarrolladores de NumPy tenían un problema que sólo podía resolverse añadiendo un nuevo método especial, `__index__()`. Cuando se utiliza la notación de trozos, como en `[start:stop:step]`, los valores de los índices start, stop y step deben ser todos enteros o enteros largos. NumPy define una variedad de tipos de enteros especializados que corresponden a enteros sin signo y con signo de 8, 16, 32 y 64 bits, pero no había forma de señalar que estos tipos pudieran usarse como índices de trozos.

El rebanado no puede utilizar el método `__int__()` existente porque ese método también se utiliza para implementar la coerción a enteros. Si el rebanado utilizara `__int__()`, los números de punto flotante también se convertirían en índices de rebanada legales y eso es claramente un comportamiento indeseable.

En su lugar, se ha añadido un nuevo método especial llamado `__index__()`. No toma argumentos y devuelve un entero que da el índice de corte a utilizar. Por ejemplo:

    class C:
        def __index__ (self):
            return self.value

El valor devuelto debe ser un entero de Python o un entero largo. El intérprete comprobará que el tipo devuelto es correcto, y lanza un `TypeError` si no se cumple este requisito.

Se agregó una ranura `nb_index` correspondiente a la estructura `PyNumberMethods` de nivel C para permitir que las extensiones C implementen este protocolo. `PyNumber_Index(obj)` se puede utilizar en código de extensión para llamar a la función `__index__()` y recuperar su resultado.

Ver también

PEP 357 - Permitir el uso de cualquier objeto para rebanar

  PEP escrito e implementado por Travis Oliphant.

## Otros cambios lingüísticos

Estos son todos los cambios que Python 2.5 introduce en el núcleo del lenguaje Python.

- El tipo `dict` tiene un nuevo gancho para permitir que las subclases proporcionen un valor por defecto cuando una clave no está contenida en el diccionario. Cuando no se encuentre una clave, se llamará al método `missing__(key)` del diccionario. Este hook se utiliza para implementar la nueva clase `defaultdict` en el módulo `collections`. El siguiente ejemplo define un diccionario que devuelve cero para cualquier clave que falte:

      class zerodict (dict):
          def __missing__ (self, key):
              return 0

      d = zerodict({1:1, 2:2})
      print d[1], d[2]   # Prints 1, 2
      print d[3], d[4]   # Prints 0, 0

- Tanto las cadenas de 8 bits como las de Unicode tienen nuevos métodos `partition(sep)` y `rpartition(sep)` que simplifican un caso de uso común.

  El método `find(S)` se utiliza a menudo para obtener un índice que luego se utiliza para cortar la cadena y obtener las piezas que están antes y después del separador. El método `partition(sep)` condensa este patrón en una sola llamada al método que devuelve una tripleta que contiene la subcadena antes del separador, el propio separador y la subcadena después del separador. Si no se encuentra el separador, el primer elemento de la tupla es la cadena completa y los otros dos elementos están vacíos. `rpartition(sep)` también devuelve una tupla de 3 elementos, pero empieza a buscar desde el final de la cadena; la `r` significa «al revés».

  Algunos ejemplos:

      >>> ('http://www.python.org').partition('://')
      ('http', '://', 'www.python.org')
      >>> ('file:/usr/share/doc/index.html').partition('://')
      ('file:/usr/share/doc/index.html', '', '')
      >>> (u'Subject: a quick question').partition(':')
      (u'Subject', u':', u' a quick question')
      >>> 'www.python.org'.rpartition('.')
      ('www.python', '.', 'org')
      >>> 'www.python.org'.rpartition(':')
      ('', '', 'www.python.org')

  (Implementado por Fredrik Lundh tras una sugerencia de Raymond Hettinger)

- Los métodos `startswith()` y `endswith()` de los tipos de cadena aceptan ahora tuplas de cadenas para su comprobación.

      def is_image_file (nombre_archivo):
      return nombre_archivo.endswith(('.gif', '.jpg', '.tiff'))

  (Implementado por Georg Brandl tras una sugerencia de Tom Lynn)

- Las funciones incorporadas `min()` y `max()` han ganado un parámetro de palabra clave `key` análogo al argumento `key` de `sort()`. Este parámetro proporciona una función que toma un único argumento y es llamada para cada valor de la lista; `min()`/`max()` devolverá el elemento con el valor de retorno más pequeño/más grande de esta función. Por ejemplo, para encontrar la cadena más larga de una lista, puede hacer:

      L = ['medium', 'longest', 'short']
      # Prints 'longest'
      print max(L, key=len)
      # Prints 'short', because lexicographically 'short' has the largest value
      print max(L)

  (Contribución de Steven Bethard y Raymond Hettinger)

- Dos nuevas funciones incorporadas, `any()` y `all()`, evalúan si un iterador contiene algún valor verdadero o falso. `any()` devuelve `True` si cualquier valor devuelto por el iterador es verdadero; en caso contrario devolverá `False`. `all()` devuelve `True` sólo si todos los valores devueltos por el iterador se evalúan como verdaderos. (Sugerido por Guido van Rossum, e implementado por Raymond Hettinger)

- El resultado del método `__hash__()` de una clase puede ser ahora un entero largo o un entero normal. Si se devuelve un entero largo, se toma el hash de ese valor. En versiones anteriores se requería que el valor del hash fuera un entero regular, pero en 2.5 el built-in `id()` se cambió para devolver siempre números no negativos, y los usuarios parecen utilizar a menudo `id(self)` en los métodos `__hash__()` (aunque esto se desaconseja).

- ASCII es ahora la codificación por defecto para los módulos. Ahora es un error de sintaxis si un módulo contiene literales de cadena con caracteres de 8 bits pero no tiene una declaración de codificación. En Python 2.4 esto provocaba una advertencia, no un error de sintaxis. Vea en PEP 263 cómo declarar la codificación de un módulo; por ejemplo, puede añadir una línea como ésta cerca de la parte superior del fichero fuente:

      #-*- coding: latin1 -*-

- Una nueva advertencia, `UnicodeWarning`, se activa cuando se intenta comparar una cadena Unicode y una cadena de 8 bits que no se puede convertir a Unicode utilizando la codificación ASCII por defecto. El resultado de la comparación es falso:

      >>> chr(128) == unichr(128)   # Can't convert chr(128) to Unicode
      __main__:1: UnicodeWarning: Unicode equal comparison failed
        to convert both arguments to Unicode - interpreting them
        as being unequal
      False
      >>> chr(127) == unichr(127)   # chr(127) can be converted
      True

  Anteriormente, esto lanzaba una excepción `UnicodeDecodeError`, pero en 2.5 esto podía dar lugar a problemas desconcertantes al acceder a un diccionario. Si se buscaba `unichr(128)` y se utilizaba `chr(128)` como clave, se producía una excepción `UnicodeDecodeError`. Otros cambios en la versión 2.5 hicieron que esta excepción se lanzara en lugar de ser suprimida por el código de `dictobject.c` que implementa los diccionarios.

  Lanzar una excepción para tal comparación es estrictamente correcto, pero el cambio podría haber roto el código, así que en su lugar se introdujo `UnicodeWarning`.

  (Implementado por Marc-André Lemburg.)

- Un error que a veces cometen los programadores de Python es olvidarse de incluir un módulo `__init__.py` en el directorio de un paquete. Depurar este error puede ser confuso, y normalmente requiere ejecutar Python con el modificador `-v` para registrar todas las rutas buscadas. En Python 2.5, una nueva advertencia `ImportWarning` se activa cuando una importación habría recogido un directorio como paquete pero no se encontró ningún `__init__.py`. Esta advertencia se ignora silenciosamente por defecto; proporcione la opción `-Wd` cuando ejecute el ejecutable de Python para mostrar el mensaje de advertencia. (Implementado por Thomas Wouters)</-W>

- La lista de clases base en una definición de clase ahora puede estar vacía. Como ejemplo, esto es ahora legal:

      clase C():
          pass

  (Implementado por Brett Cannon.)

### Cambios en el intérprete interactivo

En el intérprete interactivo, `quit` y `exit` han sido durante mucho tiempo cadenas para que los nuevos usuarios obtengan un mensaje algo útil cuando intenten salir:

    >>> salir
    'Utilice Ctrl-D (es decir, EOF) para salir.'

En Python 2.5, `quit` y `exit` son ahora objetos que siguen produciendo representaciones de cadena de sí mismos, pero también son invocables. Los novatos que prueben `quit()` o `exit()` ahora saldrán del intérprete como se espera. (Implementado por Georg Brandl.)

El ejecutable de Python ahora acepta las opciones largas estándar `--help` y `--version`; en Windows, también acepta la opción `/?` para mostrar un mensaje de ayuda. (Implementado por Georg Brandl)

### Optimizaciones

Varias de las optimizaciones se desarrollaron en el sprint NeedForSpeed, un evento celebrado en Reikiavik, Islandia, del 21 al 28 de mayo de 2006. El sprint se centró en las mejoras de velocidad de la implementación de CPython y fue financiado por EWT LLC con el apoyo local de CCP Games. Las optimizaciones añadidas en este sprint están especialmente marcadas en la siguiente lista.

- Cuando se introdujeron en Python 2.4, los tipos incorporados `set` y `frozenset` se construyeron sobre el tipo diccionario de Python. En 2.5 la estructura de datos interna se ha personalizado para implementar conjuntos, y como resultado los conjuntos utilizarán un tercio menos de memoria y son algo más rápidos. (Implementado por Raymond Hettinger)

- Se ha mejorado la velocidad de algunas operaciones Unicode, como la búsqueda de subcadenas, la división de cadenas y la codificación y decodificación de mapas de caracteres. (Las mejoras en la búsqueda de subcadenas y la división fueron añadidas por Fredrik Lundh y Andrew Dalke en el sprint NeedForSpeed. Los mapas de caracteres fueron mejorados por Walter Dörwald y Martin von Löwis)

- La función `long(str, base)` es ahora más rápida en cadenas de dígitos largos porque se calculan menos resultados intermedios. El máximo es para cadenas de alrededor de 800-1000 dígitos, donde la función es 6 veces más rápida. (Aportado por Alan McIntyre y comprometido en el sprint NeedForSpeed)

- Ahora es ilegal mezclar la iteración sobre un archivo con `for line in file` y llamar a los métodos `read()`/`readline()`/`readlines()` del objeto de archivo. La iteración utiliza un búfer interno y los métodos `read*()` no utilizan ese búfer. En su lugar, devolverían los datos después del búfer, lo que haría que los datos aparecieran desordenados. Mezclar la iteración y estos métodos ahora activará un `ValueError` desde el método `read*()`. (Implementado por Thomas Wouters).

- El módulo `struct` ahora compila cadenas de formato de estructura en una representación interna y almacena en caché esta representación, lo que supone una mejora del 20% s. (Contribuido por Bob Ippolito en el sprint NeedForSpeed)

- El módulo `re` obtuvo un 1 o 2% s de velocidad al cambiar a las funciones asignadoras de Python en lugar de las `malloc()` y `free()` del sistema. (Contribuido por Jack Diederich en el sprint NeedForSpeed)

- El optimizador de la mirilla del generador de código realiza ahora un simple plegado de constantes en las expresiones. Si escribes algo como `a = 2+3`, el generador de código hará la aritmética y producirá el código correspondiente a `a = 5`. (Propuesto e implementado por Raymond Hettinger)

- Las llamadas a funciones son ahora más rápidas porque los objetos de código guardan ahora el último fotograma terminado (un «fotograma zombi») en un campo interno del objeto de código, reutilizándolo la próxima vez que se invoque el objeto de código. (Parche original de Michael Hudson, modificado por Armin Rigo y Richard Jones; confirmado en el sprint NeedForSpeed) Los objetos marco son también ligeramente más pequeños, lo que puede mejorar la localidad de la caché y reducir un poco el uso de la memoria. (Contribución de Neal Norwitz)

- Las excepciones incorporadas en Python son ahora clases de nuevo estilo, un cambio que acelera considerablemente la instanciación. El manejo de excepciones en Python 2.5 es, por tanto, un 30% f más rápido que en 2.4. (Contribución de Richard Jones, Georg Brandl y Sean Reifschneider en el sprint NeedForSpeed)

- La importación ahora almacena en caché las rutas intentadas, registrando si existen o no para que el intérprete haga menos llamadas a `open()` y `stat()` al iniciar. (Contribución de Martin von Löwis y Georg Brandl)

## Módulos nuevos, mejorados y eliminados

La biblioteca estándar ha recibido muchas mejoras y correcciones de errores en Python 2.5. Aquí hay una lista parcial de los cambios más notables, ordenados alfabéticamente por el nombre del módulo. Consulte el archivo `Misc/NEWS` en el árbol de fuentes para obtener una lista más completa de los cambios, o busque en los registros de SVN para obtener todos los detalles.

- El módulo `audioop` ahora admite la codificación a-LAW y se ha mejorado el código para la codificación u-LAW. (Contribución de Lars Immisch).

- El módulo `codecs` ha ganado soporte para códecs incrementales. La función `codec.lookup()` devuelve ahora una instancia de `CodecInfo` en lugar de una tupla. Las instancias de `CodecInfo` se comportan como una cuádruple tupla para preservar la compatibilidad con versiones anteriores, pero también tienen los atributos `encode`, `decode`, `incrementalencoder`, `incrementaldecoder`, `streamwriter` y `streamreader`. Los códecs incrementales pueden recibir la entrada y producir la salida en varios trozos; la salida es la misma que si la entrada completa fuera alimentada por el códec no incremental. Consulte la documentación del módulo `codecs` para más detalles. (Diseñado e implementado por Walter Dörwald)

- El módulo `collections` ha ganado un nuevo tipo, `defaultdict`, que subclasifica el tipo estándar `dict`. El nuevo tipo se comporta principalmente como un diccionario pero construye un valor por defecto cuando una clave no está presente, añadiéndolo automáticamente al diccionario para el valor de la clave solicitada.

  El primer argumento del constructor de `defaultdict` es una función de fábrica que se llama cada vez que se solicita una clave pero no se encuentra. Esta función de fábrica no recibe argumentos, por lo que puede utilizar constructores de tipo incorporado como `list()` o `int()`. Por ejemplo, puedes hacer un índice de palabras basado en su letra inicial así:

      palabras = """Nel mezzo del cammin di nuestra vita
      mi ritrovai per una selva oscura
      che la diritta via era smarrita""".lower().split()

      índice = dictamen predeterminado (lista)

      para w en palabras:
          letra_inicial = w[0]
          índice[letra_inicio].append(w)

  Al imprimir `index` se obtiene la siguiente salida:

      defaultdict(<type 'list'>, {'c': ['cammin', 'che'], 'e': ['era'],
              'd': ['del', 'di', 'diritta'], 'm': ['mezzo', 'mi'],
              'l': ['la'], 'o': ['oscura'], 'n': ['nel', 'nostra'],
              'p': ['per'], 's': ['selva', 'smarrita'],
              'r': ['ritrovai'], 'u': ['una'], 'v': ['vita', 'via']}

  (Contribución de Guido van Rossum.)

- El tipo de cola doble `deque` suministrado por el módulo `collections` tiene ahora un método `remove(value)` que elimina la primera aparición de value en la cola, lanzando `ValueError` si no se encuentra el valor. (Contribución de Raymond Hettinger)

- Nuevo módulo: El módulo `contextlib` contiene funciones de ayuda para usar con la nueva sentencia “`with`”. Consulte la sección El módulo contextlib para obtener más información sobre este módulo.

- Nuevo módulo: El módulo `cProfile` es una implementación en C del módulo existente `profile` que tiene una sobrecarga mucho menor. La interfaz del módulo es la misma que la de `profile`: se ejecuta `cProfile.run('main()')` para perfilar una función, se pueden guardar los datos del perfil en un archivo, etc. Todavía no se sabe si el perfilador Hotshot, que también está escrito en C pero no coincide con la interfaz del módulo `profile`, seguirá manteniéndose en futuras versiones de Python. (Contribución de Armin Rigo.)

  Además, el módulo `pstats` para analizar los datos medidos por el perfilador ahora soporta dirigir la salida a cualquier objeto archivo suministrando un argumento stream al constructor `Stats`. (Contribución de Skip Montanaro)

- El módulo `csv`, que analiza archivos en formato de valores separados por comas, recibió varias mejoras y varias correcciones de errores. Ahora puede establecer el tamaño máximo en bytes de un campo llamando a la función `csv.field_size_limit(new_limit)`; omitir el argumento new_limit devolverá el límite establecido actualmente. La clase `reader` ahora tiene un atributo `line_num` que cuenta la cantidad de líneas físicas leídas de la fuente; los registros pueden abarcar varias líneas físicas, por lo que `line_num` no es lo mismo que el número de registros leídos.

  El analizador CSV es ahora más estricto con los campos entrecomillados de varias líneas. Anteriormente, si una línea terminaba dentro de un campo entre comillas sin un carácter de nueva línea final, se insertaba una nueva línea en el campo devuelto. Este comportamiento causaba problemas cuando se leían archivos que contenían caracteres de retorno de carro dentro de los campos, por lo que se cambió el código para devolver el campo sin insertar nuevas líneas. Como consecuencia, si las nuevas líneas incrustadas dentro de los campos son importantes, la entrada debe dividirse en líneas de manera que se conserven los caracteres de nueva línea.

  (Contribución de Skip Montanaro y Andrew McNamara)

- La clase `datetime` del módulo `datetime` tiene ahora un método `strptime(string, format)` para analizar cadenas de fechas, aportado por Josh Spoerri. Utiliza los mismos caracteres de formato que `time.strptime()` y `time.strftime()`:

      from datetime import datetime

      ts = datetime.strptime('10:13:15 2006-03-07',
                             '%H:%M:%S %Y-%m-%d')

- El método `SequenceMatcher.get_matching_blocks()` del módulo `difflib` garantiza ahora la devolución de una lista mínima de bloques que describen subsecuencias coincidentes. Anteriormente, el algoritmo rompía ocasionalmente un bloque de elementos coincidentes en dos entradas de la lista. (Mejora realizada por Tim Peters)

- El módulo `doctest` ha ganado una opción `SKIP` que impide que un ejemplo se ejecute en absoluto. Esto está pensado para los fragmentos de código que son ejemplos de uso destinados al lector y que no son realmente casos de prueba.

  Se ha añadido un parámetro encoding a la función `testfile()` y a la clase `DocFileSuite` para especificar la codificación del archivo. Esto facilita el uso de caracteres no ASCII en las pruebas contenidas en un docstring. (Contribución de Bjorn Tillenius)

- El paquete `email` ha sido actualizado a la versión 4.0. (Contribución de Barry Warsaw.)

- El módulo `fileinput` se hizo más flexible. Ahora se admiten los nombres de archivo Unicode y se agregó un parámetro mode que tiene como valor predeterminado `"r"` a la función `input()` para permitir la apertura de archivos en modo binario o universal newlines. Otro parámetro nuevo, openhook, le permite usar una función distinta de `open()` para abrir los archivos de entrada. Una vez que esté iterando sobre el conjunto de archivos, el nuevo `fileno()` del objeto `FileInput` devuelve el descriptor de archivo para el archivo abierto actualmente. (Contribuido por Georg Brandl.)

- En el módulo `gc`, la nueva función `get_count()` devuelve una 3-tupla que contiene los recuentos de recolección actuales para las tres generaciones de GC. Se trata de información contable para el recolector de basura; cuando estos recuentos alcanzan un umbral especificado, se realiza un barrido de recolección de basura. La función `gc.collect()` existente ahora toma un argumento opcional generación de 0, 1 o 2 para especificar qué generación recoger. (Contribución de Barry Warsaw)

- Las funciones `nsmallest()` y `nlargest()` del módulo `heapq` soportan ahora un parámetro de palabra clave `key` similar al proporcionado por las funciones `min()`/`max()` y los métodos `sort()`. Por ejemplo:

      >>> import heapq
      >>> L = ["short", 'medium', 'longest', 'longer still']
      >>> heapq.nsmallest(2, L)  # Return two lowest elements, lexicographically
      ['longer still', 'longest']
      >>> heapq.nsmallest(2, L, key=len)   # Return two shortest elements
      ['short', 'medium']

  (Contribución de Raymond Hettinger.)

- La función `itertools.islice()` ahora acepta `None` para los argumentos de inicio y paso. Esto la hace más compatible con los atributos de los objetos slice, por lo que ahora se puede escribir lo siguiente:

      s = slice(5) # Crear objeto slice
      itertools.islice(iterable, s.start, s.stop, s.step)

  (Contribución de Raymond Hettinger.)

- Se ha modificado la función `format()` del módulo `locale` y se han añadido dos nuevas funciones, `format_string()` y `currency()`.

  El parámetro val de la función `format()` podía ser antes una cadena siempre que no apareciera más de un especificador %char; ahora el parámetro debe ser exactamente un especificador %char sin texto alrededor. También se ha añadido un parámetro opcional monetario que, si es `Verdadero`, utilizará las reglas de la configuración regional para formatear la moneda al colocar un separador entre grupos de tres dígitos.

  Para formatear cadenas con múltiples especificadores %char, utilice la nueva función `format_string()` que funciona como `format()` pero que también permite mezclar especificadores %char con texto arbitrario.

  También se ha añadido una nueva función `currency()` que formatea un número de acuerdo con la configuración local actual.

  (Contribución de Georg Brandl.)

- El módulo `mailbox` ha sido reestructurado de forma masiva para añadir la capacidad de modificar los buzones además de leerlos. Un nuevo conjunto de clases que incluyen `mbox`, `MH`, y `Maildir` se utilizan para leer buzones, y tienen un método `add(message)` para añadir mensajes, `remove(key)` para eliminar mensajes, y `lock()`/`unlock()` para bloquear/desbloquear el buzón. El siguiente ejemplo convierte un buzón con formato maildir en uno con formato mbox:

      importar buzón

      # 'factory=None' utiliza email.Message.Message como la clase que representa
      # los mensajes individuales.
      src = mailbox.Maildir('maildir', factory=None)
      dest = mailbox.mbox('/tmp/mbox')

      para msg en src:
      dest.add(msg)

  (Contribución de Gregory K. Johnson. La financiación fue proporcionada por el Summer of Code 2005 de Google)

- Nuevo módulo: el módulo `msilib` permite crear archivos `.msi` y archivos CAB de Microsoft Installer. También se incluye cierta compatibilidad para leer la base de datos `.msi`. (Contribución de Martin von Löwis).

- El módulo `nis` ahora permite acceder a dominios distintos del dominio predeterminado del sistema mediante el suministro de un argumento domain a las funciones `nis.match()` y `nis.maps()`. (Contribuido por Ben Bell).

- Las funciones `operator` del módulo `itemgetter()` y `attrgetter()` ahora soportan múltiples campos. Una llamada como `operator.attrgetter('a', 'b')` devolverá una función que recupera los atributos `a` y `b`. La combinación de esta nueva función con el parámetro `key` del método `sort()` permite ordenar fácilmente las listas utilizando varios campos. (Contribución de Raymond Hettinger)

- El módulo `optparse` se ha actualizado a la versión 1.5.1 de la biblioteca Optik. La clase `OptionParser` obtuvo un atributo `epilog`, una cadena que se imprimirá después del mensaje de ayuda, y un método `destroy()` para romper los ciclos de referencia creados por el objeto. (Contribuido por Greg Ward.)

- El módulo `os` ha sufrido varios cambios. La variable `stat_float_times` ahora está predeterminada a true, lo que significa que `os.stat()` ahora devolverá los valores de tiempo como flotantes. (Esto no significa necesariamente que `os.stat()` devolverá tiempos con una precisión de fracciones de segundo; no todos los sistemas soportan dicha precisión)

  Se han añadido las constantes `os.SEEK_SET`, `os.SEEK_CUR` y `os.SEEK_END`, que son los parámetros de la función `os.lseek()`. Dos nuevas constantes para el bloqueo son `os.O_SHLOCK` y `os.O_EXLOCK`.

  Se han añadido dos nuevas funciones, `wait3()` y `wait4()`. Son similares a la función `waitpid()` que espera la salida de un proceso hijo y devuelve una tupla con el ID del proceso y su estado de salida, pero `wait3()` y `wait4()` devuelven información adicional. `wait3()` no toma un ID de proceso como entrada, por lo que espera a que cualquier proceso hijo salga y devuelve una tupla de id de proceso, estado de salida, uso de recursos tal y como se devuelve desde la función `resource.getrusage()`. `wait4(pid)` toma un ID de proceso. (Contribuido por Chad J. Schroeder.)

  En FreeBSD, la función `os.stat()` devuelve ahora tiempos con resolución de nanosegundos, y el objeto devuelto tiene ahora `st_gen` y `st_birthtime`. El atributo `st_flags` también está disponible, si la plataforma lo soporta. (Contribución de Antti Louko y Diego Pettenò)

- El depurador de Python proporcionado por el módulo `pdb` puede ahora almacenar listas de comandos a ejecutar cuando se alcanza un punto de ruptura y se detiene la ejecución. Una vez creado el punto de interrupción nº 1, introduzca `comandos 1` e introduzca una serie de comandos a ejecutar, terminando la lista con `end`. La lista de comandos puede incluir comandos que reanuden la ejecución, como `continue` o `next`. (Contribución de Grégoire Dooms.)

- Los módulos `pickle` y `cPickle` ya no aceptan un valor de retorno de `None` del método `__reduce__()`; en su lugar, el método debe devolver una tupla de argumentos. La capacidad de devolver `None` quedó obsoleta en Python 2.4, por lo que esto completa la eliminación de la función.

- El módulo `pkgutil`, que contiene varias funciones de utilidad para encontrar paquetes, fue mejorado para soportar los ganchos de importación de PEP 302 y ahora también funciona para paquetes almacenados en archivos con formato ZIP. (Contribución de Phillip J. Eby)

- El conjunto de pruebas pybench de Marc-André Lemburg se incluye ahora en el directorio `Tools/pybench`. El conjunto de pruebas pybench es una mejora del programa `pystone.py` de uso común, ya que pybench proporciona una medición más detallada de la velocidad del intérprete. Calcula el tiempo de determinadas operaciones como las llamadas a funciones, el corte de tuplas, las búsquedas de métodos y las operaciones numéricas, en lugar de realizar muchas operaciones diferentes y reducir el resultado a un único número como hace `pystone.py`.

- El módulo `pyexpat` utiliza ahora la versión 2.0 del analizador sintáctico Expat. (Contribución de Trent Mick)

- La clase `Queue` proporcionada por el módulo `Queue` ha ganado dos nuevos métodos. `join()` bloquea hasta que todos los elementos de la cola han sido recuperados y todo el trabajo de procesamiento de los elementos ha sido completado. Los hilos de trabajo llaman al otro método nuevo, `task_done()`, para indicar que el procesamiento de un elemento ha finalizado. (Contribución de Raymond Hettinger)

- Los antiguos módulos `regex` y `regsub`, obsoletos desde Python 2.0, han sido finalmente eliminados. Otros módulos eliminados: `statcache`, `tzparse`, `whrandom`.

- También se ha eliminado el directorio `lib-old`, que incluye módulos antiguos como `dircmp` y `ni`. `lib-old` no estaba en el directorio por defecto `sys.path`, así que a menos que tus programas añadan explícitamente el directorio a `sys.path`, esta eliminación no debería afectar a tu código.

- El módulo `rlcompleter` ya no depende de la importación del módulo `readline` y, por lo tanto, ahora funciona en plataformas no Unix. (Parche de Robert Kiendl.)

- Las clases `SimpleXMLRPCServer` y `DocXMLRPCServer` ahora tienen un atributo `rpc_paths` que restringe las operaciones XML-RPC a un conjunto limitado de rutas URL; el valor predeterminado es permitir solo `'/'` y `'/RPC2'`. Si se configura `rpc_paths` en `None` o en una tupla vacía, se deshabilita esta verificación de ruta.

- El módulo `socket` ahora soporta sockets `AF_NETLINK` en Linux, gracias a un parche de Philippe Biondi. Los sockets Netlink son un mecanismo específico de Linux para las comunicaciones entre un proceso en el espacio del usuario y el código del kernel; hay un artículo introductorio sobre ellos en https://www.linuxjournal.com/article/7356. En el código Python, las direcciones de netlink se representan como una tupla de 2 enteros, `(pid, group_mask)`.

  Dos nuevos métodos en objetos socket, `recv_into(buffer)` y `recvrom_into(buffer)`, almacenan los datos recibidos en un objeto que soporta el protocolo de buffer en lugar de devolver los datos como una cadena. Esto significa que puedes poner los datos directamente en un array o en un archivo mapeado en memoria.

  Los objetos Socket también han ganado métodos de acceso `getfamily()`, `gettype()` y `getproto()` para recuperar los valores de familia, tipo y protocolo del socket.

- Nuevo módulo: el módulo `spwd` proporciona funciones para acceder a la base de datos de contraseñas ocultas en sistemas que admiten contraseñas ocultas.

- El módulo `struct` es ahora más rápido porque compila cadenas de formato en objetos `Struct` con métodos `pack()` y `unpack()`. Esto es similar a cómo el módulo `re` permite crear objetos de expresión regular compilados. Puede seguir utilizando las funciones `pack()` y `unpack()` a nivel de módulo; éstas crearán objetos `Struct` y los almacenarán en caché. O puede utilizar directamente las instancias de `Struct`:

      s = struct.Struct('ih3s')

      data = s.pack(1972, 187, 'abc')
      year, number, name = s.unpack(data)

  También puedes empaquetar y desempaquetar datos hacia y desde objetos buffer directamente usando los métodos `pack_into(buffer, offset, v1, v2, ...)` y `unpack_from(buffer, offset)`. Esto te permite almacenar datos directamente en un array o en un archivo mapeado en memoria.

  (`Struct` objects fueron implementados por Bob Ippolito en el sprint NeedForSpeed. El soporte para los objetos buffer fue añadido por Martin Blais, también en el sprint NeedForSpeed)

- Los desarrolladores de Python cambiaron de CVS a Subversion durante el proceso de desarrollo de la versión 2.5. La información sobre la versión exacta de construcción está disponible como la variable `sys.subversion`, una 3-tupla de `(nombre del intérprete, nombre de la rama, rango de revisión)`. Por ejemplo, en el momento de escribir esto, mi copia de 2.5 informaba de `('CPython', 'trunk', '45313:45315')`.

  Esta información también está disponible para las extensiones de C a través de la función `Py_GetBuildInfo()` que devuelve una cadena de información de compilación como esta `"trunk:45355:45356M, Apr 13 2006, 07:42:19"`. (Contribuido por Barry Warsaw.)

- Otra nueva función, `sys._current_frames()`, devuelve los marcos de pila actuales para todos los hilos en ejecución como un diccionario que asigna los identificadores de los hilos al marco de pila superior actualmente activo en ese hilo en el momento en que se llama a la función. (Contribuido por Tim Peters.)

- La clase `TarFile` del módulo `tarfile` tiene ahora un método `extractall()` que extrae todos los miembros del archivo en el directorio de trabajo actual. También es posible establecer un directorio diferente como destino de la extracción, y desempaquetar sólo un subconjunto de los miembros del archivo.

  La compresión utilizada para un archivo tar abierto en modo stream puede ahora ser autodetectada utilizando el modo `'r|*'`. (Contribución de Lars Gustäbel)

- El módulo `threading` permite ahora establecer el tamaño de la pila utilizado cuando se crean nuevos hilos. La función `stack_size([*size*])` devuelve el tamaño de pila actualmente configurado, y suministrando el parámetro opcional size establece un nuevo valor. No todas las plataformas soportan el cambio del tamaño de la pila, pero Windows, POSIX threading y OS/2 lo hacen. (Contribución de Andrew MacIntyre)

- El módulo `unicodedata` ha sido actualizado para utilizar la versión 4.1.0 de la base de datos de caracteres Unicode. La versión 3.2.0 es requerida por algunas especificaciones, por lo que sigue estando disponible como `unicodedata.ucd_3_2_0`.

- Nuevo módulo: el módulo `uuid` genera identificadores únicos universales (UUID) de acuerdo con RFC 4122. El RFC define varias versiones diferentes de UUID que se generan a partir de una cadena inicial, de propiedades del sistema o de forma puramente aleatoria. Este módulo contiene una clase `UUID` y funciones llamadas `uuid1()`, `uuid3()`, `uuid4()`, y `uuid5()` para generar diferentes versiones de UUID. (Los UUID de la versión 2 no se especifican en RFC 4122 y no están soportados por este módulo)

      >>> import uuid
      >>> # make a UUID based on the host ID and current time
      >>> uuid.uuid1()
      UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')

      >>> # make a UUID using an MD5 hash of a namespace UUID and a name
      >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
      UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')

      >>> # make a random UUID
      >>> uuid.uuid4()
      UUID('16fd2706-8baf-433b-82eb-8c7fada847da')

      >>> # make a UUID using a SHA-1 hash of a namespace UUID and a name
      >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
      UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')

  (Contribución de Ka-Ping Yee.)

- Los tipos `weakref` del módulo `WeakKeyDictionary` y `WeakValueDictionary` han obtenido nuevos métodos para iterar sobre las referencias débiles contenidas en el diccionario. Se han añadido los métodos `iterkeyrefs()` y `keyrefs()` a `WeakKeyDictionary`, y `itervaluerefs()` y `valuerefs()` a `WeakValueDictionary`. (Contribución de Fred L. Drake, Jr.)

- El módulo `webbrowser` ha recibido una serie de mejoras. Ahora se puede utilizar como un script con `python -m webbrowser`, tomando una URL como argumento; hay una serie de interruptores para controlar el comportamiento (`-n` para una nueva ventana del navegador, `-t` para una nueva pestaña). Se han añadido nuevas funciones a nivel de módulo, `open_new()` y `open_new_tab()`, para soportar esto. La función `open()` del módulo soporta una característica adicional, un parámetro autoraise que señala si se debe levantar la ventana abierta cuando sea posible. Se añadieron varios navegadores adicionales a la lista de soportados, como Firefox, Opera, Konqueror y elinks. (Contribución de Oleg Broytmann y Georg Brandl)

- El módulo `xmlrpclib` ahora admite la devolución de objetos `datetime` para el tipo de fecha XML-RPC. Proporcione `use_datetime=True` a la función `loads()` o a la clase `Unmarshaller` para habilitar esta función. (Contribuido por Skip Montanaro).

- El módulo `zipfile` ahora soporta la versión ZIP64 del formato, lo que significa que un archivo .zip ahora puede ser mayor de 4 GiB y puede contener archivos individuales mayores de 4 GiB. (Contribución de Ronald Oussoren)

- Los objetos `zlib` y `Decompress` del módulo `zlib` soportan ahora un método `copy()` que realiza una copia del estado interno del objeto y devuelve un nuevo objeto `Compress` o `Decompress`. (Contribución de Chris AtLee)

### El paquete ctypes

El paquete `ctypes`, escrito por Thomas Heller, se ha añadido a la biblioteca estándar. `ctypes` permite llamar a funciones arbitrarias en bibliotecas compartidas o DLL. Los usuarios habituales pueden recordar el módulo `dl`, que proporciona funciones para cargar bibliotecas compartidas y llamar a funciones en ellas. El paquete `ctypes` es mucho más sofisticado.

Para cargar una biblioteca compartida o DLL, debes crear una instancia de la clase `CDLL` y proporcionar el nombre o la ruta de la biblioteca compartida o DLL. Una vez hecho esto, puedes llamar a funciones arbitrarias accediendo a ellas como atributos del objeto `CDLL`.

    import ctypes

    libc = ctypes.CDLL('libc.so.6')
    result = libc.printf("Line of output\n")

Se proporcionan constructores de tipo para los distintos tipos de C: `c_int()`, `c_float()`, `c_double()`, `c_char_p()` (equivalente a char* ), etcétera. A diferencia de los tipos de Python, las versiones C son todas mutables; puede asignar a su atributo `value` para cambiar el valor envuelto. Los enteros y las cadenas de Python se convertirán automáticamente a los tipos C correspondientes, pero para otros tipos debe llamar al constructor de tipo correcto. (Y me refiero a debe; hacerlo mal a menudo resultará en que el intérprete falle con una falla de segmentación).

No debería usar `c_char_p()` con una cadena de Python cuando la función C vaya a modificar el área de memoria, porque se supone que las cadenas de Python son inmutables; romper esta regla causará errores desconcertantes. Cuando necesite un área de memoria modificable, utilice `create_string_buffer()`:

    s = "this is a string"
    buf = ctypes.create_string_buffer(s)
    libc.strfry(buf)

Se supone que las funciones en C devuelven números enteros, pero se puede establecer el atributo `restype` del objeto de la función para cambiar esto:

    >>> libc.atof('2.71828')
    -1783957616
    >>> libc.atof.restype = ctypes.c_double
    >>> libc.atof('2.71828')
    2.71828

`ctypes` también proporciona un contenedor para la API C de Python como el objeto `ctypes.pythonapi`. Este objeto libera el bloqueo global del intérprete antes de llamar a una función, porque el bloqueo debe mantenerse al llamar al código del intérprete. Hay un constructor de tipo `py_object` que creará un puntero PyObject*. Un uso simple:

    import ctypes

    d = {}
    ctypes.pythonapi.PyObject_SetItem(ctypes.py_object(d),
              ctypes.py_object("abc"),  ctypes.py_object(1))
    # d is now {'abc', 1}.

No olvide utilizar `py_object()`; si lo omite, terminará con un error de segmentación.

`ctypes` existe desde hace tiempo, pero la gente sigue escribiendo y distribuyendo módulos de extensión codificados a mano porque no se puede confiar en que `ctypes` esté presente. Quizás los desarrolladores empiecen a escribir envoltorios de Python sobre una biblioteca a la que se accede a través de `ctypes` en lugar de módulos de extensión, ahora que `ctypes` está incluido en el núcleo de Python.

Ver también

https://web.archive.org/web/20180410025338/http://starship.python.net/crew/theller/ctypes/

  La página web pre-stdlib ctypes, con un tutorial, referencia y preguntas frecuentes.

La documentación del módulo `ctypes`.

### El paquete ElementTree

Un subconjunto de la biblioteca ElementTree de Fredrik Lundh para el procesamiento de XML se ha añadido a la biblioteca estándar como `xml.etree`. Los módulos disponibles son `ElementTree`, `ElementPath` y `ElementInclude` de ElementTree 1.2.6. También se incluye el módulo acelerador `cElementTree`.

El resto de esta sección proporcionará una breve descripción general del uso de ElementTree. La documentación completa de ElementTree está disponible en https://web.archive.org/web/20201124024954/http://effbot.org/zone/element-index.htm.

ElementTree representa un documento XML como un árbol de nodos de elementos. El contenido de texto del documento se almacena como los atributos `text` y `tail` de (Esta es una de las principales diferencias entre ElementTree y el Modelo de Objetos del Documento; en el DOM hay muchos tipos diferentes de nodo, incluyendo `TextNode`)

La función de análisis más utilizada es `parse()`, que toma una cadena (se supone que contiene un nombre de archivo) o un objeto similar a un archivo y devuelve una instancia de `ElementTree`:

    from xml.etree import ElementTree as ET

    tree = ET.parse('ex-1.xml')

    feed = urllib.urlopen(
              'http://planet.python.org/rss10.xml')
    tree = ET.parse(feed)

Una vez que tengas una instancia de `ElementTree`, puedes llamar a su método `getroot()` para obtener el nodo raíz de `Element`.

También hay una función `XML()` que toma un literal de cadena y devuelve un nodo `Element` (no un `ElementTree`). Esta función proporciona una forma ordenada de incorporar fragmentos XML, acercándose a la comodidad de un literal XML:

    svg = ET.XML("""<svg width="10px" version="1.0">
                 </svg>""")
    svg.set('height', '320px')
    svg.append(elem1)

Cada elemento XML admite algunos métodos de acceso tipo diccionario y otros tipo lista. Las operaciones tipo diccionario se utilizan para acceder a los valores de los atributos, y las operaciones tipo lista se utilizan para acceder a los nodos hijos.

Operación | Resultado
--- | ---
`elem[n]` | Devuelve el elemento hijo enésimo.
`elem[m:n]` | Devuelve la lista de m’s a n’s elementos hijos.
`len(elem)` | Devuelve el número de elementos hijos.
`lista(elem)` | Devuelve la lista de elementos hijos.
`elem.append(elem2)` | Añade elemento2 como hijo.
`elem.insert(index, elem2)` | Inserta elemento2 en el lugar especificado.
`del elem[n]` | Elimina el elemento hijo enésimo.
`elem.keys()` | Devuelve la lista de nombres de atributos.
`elem.get(name)` | Devuelve el valor del atributo nombre.
`elem.set(nombre, valor)` | Establece el nuevo valor del atributo nombre.
`elem.attrib` | Recupera el diccionario que contiene los atributos.
`del elem.attrib[name]` | Borra el atributo nombre.

Los comentarios y las instrucciones de procesamiento también se representan como nodos `Element`. Para comprobar si un nodo es un comentario o unas instrucciones de procesamiento:

    if elem.tag is ET.Comment:
        ...
    elif elem.tag is ET.ProcessingInstruction:
        ...

Para generar una salida XML, debes llamar al método `ElementTree.write()`. Al igual que `parse()`, puede tomar una cadena o un objeto tipo archivo:

    # Encoding is US-ASCII
    tree.write('output.xml')

    # Encoding is UTF-8
    f = open('output.xml', 'w')
    tree.write(f, encoding='utf-8')

(Atención: la codificación por defecto utilizada para la salida es ASCII. Para el trabajo general de XML, donde el nombre de un elemento puede contener caracteres Unicode arbitrarios, ASCII no es una codificación muy útil porque lanzará una excepción si el nombre de un elemento contiene cualquier carácter con valores superiores a 127. Por lo tanto, es mejor especificar una codificación diferente, como UTF-8, que puede manejar cualquier carácter Unicode)

Esta sección es sólo una descripción parcial de las interfaces de ElementTree. Por favor, lee la documentación oficial del paquete para más detalles.

Ver también

https://web.archive.org/web/20201124024954/http://effbot.org/zone/element-index.htm

  Documentación oficial de ElementTree.

### El paquete hashlib

Se ha añadido un nuevo módulo `hashlib`, escrito por Gregory P. Smith, para sustituir a los módulos `md5` y `sha`. `hashlib` añade compatibilidad con hashes seguros adicionales (SHA-224, SHA-256, SHA-384 y SHA-512). Cuando está disponible, el módulo utiliza OpenSSL para implementaciones rápidas y optimizadas de algoritmos para plataformas.

Los módulos antiguos `md5` y `sha` todavía existen como contenedores de hashlib para preservar la compatibilidad con versiones anteriores. La interfaz del nuevo módulo es muy similar a la de los módulos antiguos, pero no idéntica. La diferencia más significativa es que las funciones constructoras para crear nuevos objetos hash tienen nombres diferentes.

    # Versiones anteriores
    h = md5.md5()
    h = md5.new()

    # Nueva versión
    h = hashlib.md5()

    # Versiones anteriores
    h = sha.sha()
    h = sha.new()

    # Nueva versión
    h = hashlib.sha1()

    # Hash que no estaban disponibles anteriormente
    h = hashlib.sha224()
    h = hashlib.sha256()
    h = hashlib.sha384()
    h = hashlib.sha512()

    # Forma alternativa
    h = hashlib.new('md5') # Proporcionar algoritmo como cadena

Una vez que se ha creado un objeto hash, sus métodos son los mismos que antes: `actualizar(cadena)` convierte la cadena especificada en el estado de resumen actual, `digest()` y `hexdigest()` devuelven el valor de resumen como una cadena binaria o una cadena de dígitos hexadecimales, y `copiar()` devuelve un nuevo objeto hash con el mismo estado de resumen.

Ver también

La documentación del módulo `hashlib`.

### El paquete sqlite3

El módulo pysqlite (https://www.pysqlite.org), un envoltorio para la base de datos incrustada de SQLite, se agregó a la biblioteca estándar con el nombre de paquete `sqlite3`.

SQLite es una biblioteca en C que proporciona una base de datos ligera basada en disco que no requiere un proceso de servidor independiente y permite acceder a la base de datos utilizando una variante no estándar del lenguaje de consulta SQL. Algunas aplicaciones pueden utilizar SQLite para el almacenamiento interno de datos. También es posible crear un prototipo de una aplicación utilizando SQLite y luego portar el código a una base de datos más grande como PostgreSQL u Oracle.

pysqlite fue escrito por Gerhard Häring y proporciona una interfaz SQL que cumple con la especificación DB-API 2.0 descrita por PEP 249.

Si estás compilando el código fuente de Python tú mismo, ten en cuenta que el árbol de código fuente no incluye el código de SQLite, sólo el módulo envolvente. Necesitarás tener las librerías y cabeceras de SQLite instaladas antes de compilar Python, y el proceso de construcción compilará el módulo cuando las cabeceras necesarias estén disponibles.

Para utilizar el módulo, primero hay que crear un objeto `Connection` que represente la base de datos. Aquí los datos se almacenarán en el archivo `/tmp/example`:

    conn = sqlite3.connect('/tmp/ejemplo')

También puede suministrar el nombre especial `:memory:` para crear una base de datos en la RAM.

Una vez que tengas una `Connection`, puedes crear un objeto `Cursor` y llamar a su método `execute()` para realizar comandos SQL:

    c = conn.cursor()

    # Create table
    c.execute('''create table stocks
    (date text, trans text, symbol text,
     qty real, price real)''')

    # Insert a row of data
    c.execute("""insert into stocks
              values ('2006-01-05','BUY','RHAT',100,35.14)""")

Normalmente tus operaciones SQL necesitarán usar valores de variables de Python. No deberías montar tu consulta usando las operaciones de cadena de Python porque hacerlo es inseguro; hace que tu programa sea vulnerable a un ataque de inyección SQL.

En su lugar, utilice la sustitución de parámetros de la DB-API. Ponga `?` como marcador de posición donde quiera usar un valor, y luego proporcione una tupla de valores como segundo argumento al método `execute()` del cursor. (Otros módulos de base de datos pueden utilizar un marcador de posición diferente, como `%s` o `:1`) Por ejemplo:

    # Never do this -- insecure!
    symbol = 'IBM'
    c.execute("... where symbol = '%s'" % symbol)

    # Do this instead
    t = (symbol,)
    c.execute('select * from stocks where symbol=?', t)

    # Larger example
    for t in (('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
              ('2006-04-05', 'BUY', 'MSOFT', 1000, 72.00),
              ('2006-04-06', 'SELL', 'IBM', 500, 53.00),
             ):
        c.execute('insert into stocks values (?,?,?,?,?)', t)

Para recuperar datos después de ejecutar una sentencia SELECT, puede tratar el cursor como un iterador, llamar al método `fetchone()` del cursor para recuperar una sola fila que coincida, o llamar a `fetchall()` para obtener una lista de las filas que coincidan.

Este ejemplo utiliza la forma del iterador:

    >>> c = conn.cursor()
    >>> c.execute('select * from stocks order by price')
    >>> for row in c:
    ...    print row
    ...
    (u'2006-01-05', u'BUY', u'RHAT', 100, 35.140000000000001)
    (u'2006-03-28', u'BUY', u'IBM', 1000, 45.0)
    (u'2006-04-06', u'SELL', u'IBM', 500, 53.0)
    (u'2006-04-05', u'BUY', u'MSOFT', 1000, 72.0)
    >>>

Para más información sobre el dialecto SQL soportado por SQLite, consulte https://www.sqlite.org.

Ver también

https://www.pysqlite.org

  La página web de pysqlite.

https://www.sqlite.org

  La página web de SQLite; la documentación describe la sintaxis y los tipos de datos disponibles para el dialecto SQL soportado.

La documentación del módulo `sqlite3`.

PEP 249 - Especificación de la API de la base de datos 2.0

  PEP escrito por Marc-André Lemburg.

### El paquete wsgiref

La Interfaz de Pasarela del Servidor Web (WSGI) v1.0 define una interfaz estándar entre los servidores web y las aplicaciones web de Python y se describe en PEP 333. El paquete `wsgiref` es una implementación de referencia de la especificación WSGI.

El paquete incluye un servidor HTTP básico que ejecutará una aplicación WSGI; este servidor es útil para la depuración pero no está pensado para su uso en producción. La configuración de un servidor sólo requiere unas pocas líneas de código:

    from wsgiref import simple_server

    wsgi_app = ...

    host = ''
    port = 8000
    httpd = simple_server.make_server(host, port, wsgi_app)
    httpd.serve_forever()

Ver también

https://web.archive.org/web/20160331090247/http://wsgi.readthedocs.org/en/latest/

  Un sitio web central para los recursos relacionados con WSGI.

PEP 333 - Interfaz del servidor web Python v1.0

  PEP escrito por Phillip J. Eby.

## Cambios en la API de construcción y C

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

- El árbol de fuentes de Python fue convertido de CVS a Subversion, en un complejo procedimiento de migración que fue supervisado y llevado a cabo de forma impecable por Martin von Löwis. El procedimiento se desarrolló como PEP 347.

- Coverity, una empresa que comercializa una herramienta de análisis de código fuente llamada Prevent, proporcionó los resultados de su examen del código fuente de Python. El análisis encontró alrededor de 60 errores que fueron rápidamente corregidos. Muchos de los errores eran problemas de recuento, que a menudo se producen en el código de gestión de errores. Consulte las estadísticas en https://scan.coverity.com.

- El mayor cambio en la API de C provino de PEP 353, que modifica el intérprete para usar una definición de tipo `Py_ssize_t` en lugar de int. Consulte la sección anterior PEP 353: Uso de ssize_t como tipo de índice para obtener una explicación de este cambio.

- El diseño del compilador de código de bytes ha cambiado mucho, ya no genera código de bytes recorriendo el árbol de análisis sintáctico. En su lugar, el árbol de análisis se convierte en un árbol de sintaxis abstracta (o AST), y es el árbol de sintaxis abstracta el que se recorre para producir el código de bytes.

  Es posible que el código Python obtenga objetos AST utilizando el built-in `compile()` y especificando `_ast.PyCF_ONLY_AST` como valor del parámetro flags:

      from _ast import PyCF_ONLY_AST
      ast = compile("""a=0
      for i in range(10):
          a += i
      """, "<string>", 'exec', PyCF_ONLY_AST)

      assignment = ast.body[0]
      for_loop = ast.body[1]

  Todavía no se ha escrito ninguna documentación oficial para el código AST, pero PEP 339 discute el diseño. Para empezar a conocer el código, lea la definición de los distintos nodos AST en `Parser/Python.asdl`. Un script de Python lee este archivo y genera un conjunto de definiciones de estructuras C en `Include/Python-ast.h`. Las funciones `PyParser_ASTFromString()` y `PyParser_ASTFromFile()`, definidas en `Include/pythonrun.h`, toman el código fuente de Python como entrada y devuelven la raíz de un AST que representa el contenido. Este AST puede convertirse en un objeto de código mediante `PyAST_Compile()`. Para más información, lea el código fuente, y luego haga preguntas en python-dev.

  El código de la AST fue desarrollado bajo la dirección de Jeremy Hylton, e implementado por (en orden alfabético) Brett Cannon, Nick Coghlan, Grant Edwards, John Ehresman, Kurt Kaiser, Neal Norwitz, Tim Peters, Armin Rigo y Neil Schemenauer, además de los participantes en varios sprints de la AST en conferencias como la PyCon.

- Se aplicó el parche de Evan Jones a obmalloc, descrito por primera vez en una charla en la PyCon DC 2005. Python 2.4 asignaba objetos pequeños en arenas de 256K, pero nunca liberaba arenas. Con este parche, Python liberará arenas cuando estén vacías. El efecto neto es que en algunas plataformas, cuando se asignan muchos objetos, el uso de la memoria de Python puede realmente caer cuando se borran y la memoria puede ser devuelta al sistema operativo. (Implementado por Evan Jones, y reelaborado por Tim Peters)

  Tenga en cuenta que este cambio significa que los módulos de extensión deben ser más cuidadosos al asignar memoria. La API de Python tiene muchas funciones diferentes para asignar memoria que se agrupan en familias. Por ejemplo, `PyMem_Malloc()`, `PyMem_Realloc()`, y `PyMem_Free()` son una familia que asigna memoria en bruto, mientras que `PyObject_Malloc()`, `PyObject_Realloc()`, y `PyObject_Free()` son otra familia que se supone que se utiliza para crear objetos de Python.

  Anteriormente estas diferentes familias se reducían a las funciones `malloc()` y `free()` de la plataforma. Esto significaba que no importaba si te equivocabas y asignabas memoria con la función `PyMem` pero la liberabas con la función `PyObject`. Con los cambios de la versión 2.5 en obmalloc, estas familias hacen ahora cosas diferentes y los desajustes probablemente darán lugar a un fallo de seguridad. Deberías probar cuidadosamente tus módulos de extensión C con Python 2.5.

- Los tipos de conjuntos incorporados tienen ahora una API oficial en C. Llame a `PySet_New()` y `PyFrozenSet_New()` para crear un nuevo conjunto, `PySet_Add()` y `PySet_Discard()` para añadir y eliminar elementos, y `PySet_Contains()` y `PySet_Size()` para examinar el estado del conjunto. (Contribución de Raymond Hettinger)

- El código C puede ahora obtener información sobre la revisión exacta del intérprete de Python llamando a la función `Py_GetBuildInfo()` que devuelve una cadena de información de compilación como esta `"trunk:45355:45356M, Apr 13 2006, 07:42:19"`. (Contribuido por Barry Warsaw.)

- Two new macros can be used to indicate C functions that are local to the current file so that a faster calling convention can be used. `Py_LOCAL` declares the function as returning a value of the specified type and uses a fast-calling qualifier. `Py_LOCAL_INLINE` does the same thing and also requests the function be inlined. If macro `PY_LOCAL_AGGRESSIVE` is defined before `python.h` is included, a set of more aggressive optimizations are enabled for the module; you should benchmark the results to find out if these optimizations actually make the code faster. (Contributed by Fredrik Lundh at the NeedForSpeed sprint.)

- `PyErr_NewException(name, base, dict)` ahora puede aceptar una tupla de clases base como su argumento base. (Contribuido por Georg Brandl.)

- La función `PyErr_Warn()` para emitir avisos está ahora obsoleta en favor de `PyErr_WarnEx(category, message, stacklevel)` que permite especificar el número de marcos de pila que separan esta función y la que la llama. Un stacklevel de 1 es la función que llama a `PyErr_WarnEx()`, 2 es la función que está por encima, y así sucesivamente. (Añadido por Neal Norwitz.)

- El intérprete de CPython sigue estando escrito en C, pero el código ahora puede ser compilado con un compilador de C++ sin errores. (Implementado por Anthony Baxter, Martin von Löwis, Skip Montanaro)

- Se ha eliminado la función `PyRange_New()`. Nunca se documentó, nunca se utilizó en el código del núcleo, y tenía una comprobación de errores peligrosamente laxa. En el improbable caso de que sus extensiones la utilizaran, puede sustituirla por algo como lo siguiente:

      range = PyObject_CallFunction((PyObject*) &PyRange_Type, "lll",
                                    start, stop, step);

### Cambios específicos en los puertos

- MacOS X (10.3 y superior): la carga dinámica de módulos utiliza ahora la función `dlopen()` en lugar de funciones específicas de MacOS.

- MacOS X: se ha añadido una opción `--enable-universalsdk` al script configure que compila el intérprete como un binario universal capaz de funcionar tanto en procesadores PowerPC como Intel. (Contribución de Ronald Oussoren; bpo-2573.)

- Windows: `.dll` ya no se admite como extensión de nombre de archivo para los módulos de extensión. `.pyd` es ahora la única extensión de nombre de archivo que se buscará.

## Adaptación a Python 2.5

Esta sección enumera los cambios descritos anteriormente que pueden requerir cambios en su código:

- ASCII es ahora la codificación por defecto para los módulos. Ahora es un error de sintaxis si un módulo contiene literales de cadena con caracteres de 8 bits pero no tiene una declaración de codificación. En Python 2.4 esto provocaba una advertencia, no un error de sintaxis.

- Anteriormente, el atributo `gi_frame` de un generador era siempre un objeto frame. Debido a los cambios de PEP 342 descritos en la sección PEP 342: Nuevas funciones del generador, ahora es posible que `gi_frame` sea `None`.

- Una nueva advertencia, `UnicodeWarning`, se lanza cuando se intenta comparar una cadena Unicode y una cadena de 8 bits que no puede ser convertida a Unicode utilizando la codificación ASCII por defecto. Anteriormente estas comparaciones lanzaban una excepción `UnicodeDecodeError`.

- Biblioteca: el módulo `csv` es ahora más estricto con los campos citados en varias líneas. Si sus archivos contienen nuevas líneas incrustadas dentro de los campos, la entrada debe dividirse en líneas de manera que se conserven los caracteres de nueva línea.

- Biblioteca: la función `format()` del módulo `locale` aceptaba antes cualquier cadena siempre que no apareciera más de un especificador %char. En Python 2.5, el argumento debe ser exactamente un especificador %char sin texto alrededor.

- Biblioteca: Los módulos `pickle` y `cPickle` ya no aceptan un valor de retorno de `None` del método `__reduce__()`; en su lugar, el método debe devolver una tupla de argumentos. Los módulos tampoco aceptan el parámetro de palabra clave bin, que ya no se utiliza.

- Biblioteca: Las clases `SimpleXMLRPCServer` y `DocXMLRPCServer` ahora tienen un atributo `rpc_paths` que restringe las operaciones XML-RPC a un conjunto limitado de rutas URL; el valor predeterminado es permitir solo `'/'` y `'/RPC2'`. Si se configura `rpc_paths` en `None` o en una tupla vacía, se deshabilita esta verificación de ruta.

- API de C: muchas funciones ahora usan `Py_ssize_t` en lugar de int para permitir el procesamiento de más datos en máquinas de 64 bits. Es posible que el código de extensión deba realizar el mismo cambio para evitar advertencias y admitir máquinas de 64 bits. Consulte la sección anterior PEP 353: Uso de ssize_t como tipo de índice para obtener una explicación de este cambio.

- API C: Los cambios en obmalloc significan que debe tener cuidado de no mezclar el uso de las familias de funciones `PyMem_*` y `PyObject_*`. La memoria asignada con la función `*_Malloc` de una familia, debe ser liberada con la función `*_Free` de la familia correspondiente.

## Agradecimientos

El autor desea agradecer a las siguientes personas sus sugerencias, correcciones y ayuda en varios borradores de este artículo: Georg Brandl, Nick Coghlan, Phillip J. Eby, Lars Gustäbel, Raymond Hettinger, Ralf W. Grosse-Kunstleve, Kent Johnson, Iain Lowe, Martin von Löwis, Fredrik Lundh, Andrew McNamara, Skip Montanaro, Gustavo Niemeyer, Paul Prescod, James Pryor, Mike Rovner, Scott Weikart, Barry Warsaw, Thomas Wouters.