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:

   if condition:
       x = true_value
   else:
       x = false_value

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 = true_value if condition else false_value

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:

   contents = ((doc + '\n') if doc else '')

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:

   # First version -- no parens
   level = 1 if logging else 0

   # Second version -- with parens
   level = (1 if logging else 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):
       "Write the contents of 'message' to the specified subsystem."
       print '%s: %s' % (subsystem, message)
       ...

   server_log = functools.partial(log, subsystem='server')
   server_log('Unable to open 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 = (yield 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/~da
  n/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

The expression is evaluated, and it should result in an object that
supports the context management protocol (that is, has "__enter__()"
and "__exit__()" methods.

The object's "__enter__()" is called before *with-block* is executed
and therefore can run set-up code. It also may return a value that is
bound to the name *variable*, if given.  (Note carefully that
*variable* is *not* assigned the result of *expression*.)

After execution of the *with-block* is finished, the object's
"__exit__()" method is called, even if the block raised an exception,
and can therefore run clean-up code.

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

   from __future__ import with_statement

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:

  In this case, *f* is the same object created by "open()", because
  "__enter__()" returns *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:

* The expression is evaluated and should result in an object called a
  "context manager".  The context manager must have "__enter__()" and
  "__exit__()" methods.

* The context manager's "__enter__()" method is called.  The value
  returned is assigned to *VAR*.  If no "'as VAR'" clause is present,
  the value is simply discarded.

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

* If *BLOCK* didn't raise an exception,  the "__exit__()" method is
  still called, but *type*, *value*, and *traceback* are all "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"

The "__enter__()" method is pretty easy, having only to start a new
transaction.  For this application the resulting cursor object would
be a useful result, so the method will return it.  The user can then
add "as cursor" to their '"with"' statement to bind the cursor to a
variable name.

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

The "__exit__()" method is the most complicated because it's where
most of the work has to be done.  The method has to check if an
exception occurred.  If there was no exception, the transaction is
committed.  The transaction is rolled back if there was an exception.

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"'.

The decorator is called "contextmanager()", and lets you write a
single generator function instead of defining a new class.  The
generator should yield exactly one value.  The code up to the "yield"
will be executed as the "__enter__()" method, and the value yielded
will be the method's return value that will get bound to the variable
in the '"with"' statement's "as" clause, if any.  The code after the
"yield" will be executed in the "__exit__()" method.  Any exception
raised in the block will be raised by the "yield" statement.

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()
   with nested (db_transaction(db), lock) as (cursor, locked):
       ...

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.

A corresponding "nb_index" slot was added to the C-level
"PyNumberMethods" structure to let C extensions implement this
protocol. "PyNumber_Index(obj)" can be used in extension code to call
the "__index__()" function and retrieve its result.

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 (filename):
         return filename.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:

     class 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:

   >>> quit
   'Use Ctrl-D (i.e. EOF) to exit.'

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)

* It's now illegal to mix iterating over a file  with "for line in
  file" and calling  the file object's
  "read()"/"readline()"/"readlines()" methods.  Iteration uses an
  internal buffer and the  "read*()" methods don't use that buffer.
  Instead they would return the data following the buffer, causing the
  data to appear out of order.  Mixing iteration and these methods
  will now trigger a "ValueError" from the "read*()" method.
  (Implemented by 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" soporta ahora 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í:

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

     index = defaultdict(list)

     for w in words:
         init_letter = w[0]
         index[init_letter].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.)

* The "fileinput" module was made more flexible. Unicode filenames are
  now supported, and a *mode* parameter that defaults to ""r"" was
  added to the "input()" function to allow opening files in binary or
  *universal newlines* mode.  Another new parameter, *openhook*, lets
  you use a function other than "open()"  to open the input files.
  Once you're iterating over the set of files, the "FileInput"
  object's new "fileno()" returns the file descriptor for the
  currently opened file. (Contributed by 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)     # Create slice object
     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:

     import mailbox

     # 'factory=None' uses email.Message.Message as the class representing
     # individual messages.
     src = mailbox.Maildir('maildir', factory=None)
     dest = mailbox.mbox('/tmp/mbox')

     for msg in 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" de
  Microsoft Installer y archivos CAB.  También se incluye soporte para
  la lectura de la base de datos ".msi". (Contribución de Martin von
  Löwis)

* El módulo "nis" soporta ahora el acceso a dominios distintos del
  dominio por defecto del sistema proporcionando un argumento
  *dominio* a las funciones "nis.match()" y "nis.maps()".
  (Contribución de 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)

  Constants named "os.SEEK_SET", "os.SEEK_CUR", and "os.SEEK_END" have
  been added; these are the parameters to the "os.lseek()" function.
  Two new constants for locking are "os.O_SHLOCK" and "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.)

* The "pickle" and "cPickle" modules no longer accept a return value
  of "None" from the "__reduce__()" method; the method must return a
  tuple of arguments instead.  The ability to return "None" was
  deprecated in Python 2.4, so this completes the removal of the
  feature.

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

* The "SimpleXMLRPCServer" and "DocXMLRPCServer"  classes now have a
  "rpc_paths" attribute that constrains XML-RPC operations to a
  limited set of URL paths; the default is to allow only "'/'" and
  "'/RPC2'".  Setting "rpc_paths" to "None" or an empty tuple disables
  this path checking.

* 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 en la sombra en sistemas que
  soportan contraseñas en la sombra.

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

* The "unicodedata" module has been updated to use version 4.1.0 of
  the Unicode character database.  Version 3.2.0 is required  by some
  specifications, so it's still available as  "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)

* The "xmlrpclib" module now supports returning  "datetime" objects
  for the XML-RPC date type.  Supply  "use_datetime=True" to the
  "loads()" function or the "Unmarshaller" class to enable this
  feature. (Contributed by 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
-----------------

The "ctypes" package, written by Thomas Heller, has been added  to the
standard library.  "ctypes" lets you call arbitrary functions  in
shared libraries or DLLs.  Long-time users may remember the "dl"
module, which provides functions for loading shared libraries and
calling functions in them. The "ctypes" package is much fancier.

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 objeto "ctypes.pythonapi". Este objeto *not* libera el bloqueo
del intérprete global antes de llamar a una función, porque el bloqueo
debe mantenerse cuando se llama 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 olvides usar "py_object()"; si se omite acabas con un fallo 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.n
  et/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
------------------

A new "hashlib" module, written by Gregory P. Smith,  has been added
to replace the "md5" and "sha" modules.  "hashlib" adds support for
additional secure hashes (SHA-224, SHA-256, SHA-384, and SHA-512).
When available, the module uses OpenSSL for fast platform optimized
implementations of algorithms.

The old "md5" and "sha" modules still exist as wrappers around hashlib
to preserve backwards compatibility.  The new module's interface is
very close to that of the old modules, but not identical. The most
significant difference is that the constructor functions for creating
new hashing objects are named differently.

   # Old versions
   h = md5.md5()
   h = md5.new()

   # New version
   h = hashlib.md5()

   # Old versions
   h = sha.sha()
   h = sha.new()

   # New version
   h = hashlib.sha1()

   # Hash that weren't previously available
   h = hashlib.sha224()
   h = hashlib.sha256()
   h = hashlib.sha384()
   h = hashlib.sha512()

   # Alternative form
   h = hashlib.new('md5')          # Provide algorithm as a string

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/example')

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]

  No official documentation has been written for the AST code yet, but
  **PEP 339** discusses the design.  To start learning about the code,
  read the definition of the various AST nodes in
  "Parser/Python.asdl".  A Python script reads this file and generates
  a set of C structure definitions in "Include/Python-ast.h".  The
  "PyParser_ASTFromString()" and "PyParser_ASTFromFile()", defined in
  "Include/pythonrun.h", take Python source as input and return the
  root of an AST representing the contents. This AST can then be
  turned into a code object by "PyAST_Compile()".  For more
  information, read the source code, and then ask questions on 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.

  Previously these different families all reduced to the platform's
  "malloc()" and "free()" functions.  This meant  it didn't matter if
  you got things wrong and allocated memory with the "PyMem" function
  but freed it with the "PyObject" function.  With 2.5's changes to
  obmalloc, these families now do different things and mismatches will
  probably result in a segfault.  You should carefully test your C
  extension modules with 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(type)" declares the function as returning a value of the
  specified *type* and uses a fast-calling qualifier.
  "Py_LOCAL_INLINE(type)" 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.)

* The "PyErr_Warn()" function for issuing warnings is now deprecated
  in favour of "PyErr_WarnEx(category, message, stacklevel)" which
  lets you specify the number of stack frames separating this function
  and the caller.  A *stacklevel* of 1 is the function calling
  "PyErr_WarnEx()", 2 is the function above that, and so forth.
  (Added by 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)

* The "PyRange_New()" function was removed.  It was never documented,
  never used in the core code, and had dangerously lax error checking.
  In the unlikely case that your extensions were using it, you can
  replace it by something like the following:

     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.

* Library: The "pickle" and "cPickle" modules no longer accept a
  return value of "None" from the "__reduce__()" method; the method
  must return a tuple of arguments instead.  The modules also no
  longer accept the deprecated *bin* keyword parameter.

* Library: The "SimpleXMLRPCServer" and "DocXMLRPCServer"  classes now
  have a "rpc_paths" attribute that constrains XML-RPC operations to a
  limited set of URL paths; the default is to allow only "'/'" and
  "'/RPC2'". Setting  "rpc_paths" to "None" or an empty tuple disables
  this path checking.

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