Qué hay de nuevo en Python 2.3

Autor

A.M. Kuchling

Este artículo explica las nuevas características de Python 2.3. Python 2.3 se publicó el 29 de julio de 2003.

Los temas principales de Python 2.3 son el pulido de algunas de las características añadidas en la 2.2, la adición de varias mejoras pequeñas pero útiles al núcleo del lenguaje y la ampliación de la biblioteca estándar. El nuevo modelo de objetos introducido en la versión anterior se ha beneficiado de 18 meses de correcciones de errores y de esfuerzos de optimización que han mejorado el rendimiento de las clases de nuevo estilo. Se han añadido algunas funciones incorporadas, como sum() y enumerate(). El operador in puede utilizarse ahora para búsquedas de subcadenas (por ejemplo, "ab" en "abc" retorna True).

Algunas de las nuevas características de la biblioteca son los tipos de datos booleanos, de conjunto, de montón y de fecha/hora, la posibilidad de importar módulos desde archivos con formato ZIP, el soporte de metadatos para el tan esperado catálogo de Python, una versión actualizada de IDLE y módulos para registrar mensajes, envolver texto, analizar archivos CSV, procesar opciones de línea de comandos, utilizar bases de datos BerkeleyDB… la lista de módulos nuevos y mejorados es larga.

Este artículo no pretende proporcionar una especificación completa de las nuevas características, sino que proporciona una visión general conveniente. Para obtener todos los detalles, debes consultar la documentación de Python 2.3, como la Referencia de la Biblioteca de Python y el Manual de Referencia de Python. Si quieres entender la implementación completa y los fundamentos del diseño, consulta el PEP de una nueva característica en particular.

PEP 218: Un tipo de datos de conjunto estándar

El nuevo módulo sets contiene una implementación de un tipo de datos de conjuntos. La clase Set es para conjuntos mutables, conjuntos a los que se les pueden añadir y eliminar miembros. La clase ImmutableSet es para los conjuntos que no pueden ser modificados, y las instancias de ImmutableSet pueden por lo tanto ser utilizadas como claves de diccionario. Los conjuntos se construyen sobre diccionarios, por lo que los elementos de un conjunto deben ser hashables.

Aquí hay un ejemplo simple:

>>> import sets
>>> S = sets.Set([1,2,3])
>>> S
Set([1, 2, 3])
>>> 1 in S
True
>>> 0 in S
False
>>> S.add(5)
>>> S.remove(3)
>>> S
Set([1, 2, 5])
>>>

La unión y la intersección de los conjuntos pueden calcularse con los métodos union() y intersection(); una notación alternativa utiliza los operadores bitácora & y |. Los conjuntos mutables también tienen versiones in situ de estos métodos, union_update() y intersection_update().

>>> S1 = sets.Set([1,2,3])
>>> S2 = sets.Set([4,5,6])
>>> S1.union(S2)
Set([1, 2, 3, 4, 5, 6])
>>> S1 | S2                  # Alternative notation
Set([1, 2, 3, 4, 5, 6])
>>> S1.intersection(S2)
Set([])
>>> S1 & S2                  # Alternative notation
Set([])
>>> S1.union_update(S2)
>>> S1
Set([1, 2, 3, 4, 5, 6])
>>>

También es posible tomar la diferencia simétrica de dos conjuntos. Este es el conjunto de todos los elementos de la unión que no están en la intersección. Otra forma de decirlo es que la diferencia simétrica contiene todos los elementos que están exactamente en un conjunto. De nuevo, existe una notación alternativa (^), y una versión in-place con el poco agraciado nombre symmetric_difference_update().

>>> S1 = sets.Set([1,2,3,4])
>>> S2 = sets.Set([3,4,5,6])
>>> S1.symmetric_difference(S2)
Set([1, 2, 5, 6])
>>> S1 ^ S2
Set([1, 2, 5, 6])
>>>

También hay métodos issubset() y issuperset() para comprobar si un conjunto es subconjunto o superconjunto de otro:

>>> S1 = sets.Set([1,2,3])
>>> S2 = sets.Set([2,3])
>>> S2.issubset(S1)
True
>>> S1.issubset(S2)
False
>>> S1.issuperset(S2)
True
>>>

Ver también

PEP 218 - Añadiendo un tipo de objeto de conjunto incorporado

PEP escrito por Greg V. Wilson. Implementado por Greg V. Wilson, Alex Martelli y GvR.

PEP 255: Generadores simples

En Python 2.2, los generadores se añadieron como una característica opcional, que se activaba mediante una directiva from __future__ import generators. En 2.3 los generadores ya no necesitan ser habilitados especialmente, y ahora están siempre presentes; esto significa que yield es ahora siempre una palabra clave. El resto de esta sección es una copia de la descripción de los generadores del documento «What’s New in Python 2.2»; si lo leíste cuando salió Python 2.2, puedes saltarte el resto de esta sección.

Sin duda estás familiarizado con cómo funcionan las llamadas a funciones en Python o C. Cuando llamas a una función, ésta obtiene un espacio de nombres privado donde se crean sus variables locales. Cuando la función llega a una declaración return, las variables locales se destruyen y el valor resultante se retorna a quien la llamó. Una llamada posterior a la misma función obtendrá un nuevo conjunto de variables locales. Pero, ¿qué pasaría si las variables locales no se tiraran al salir de una función? ¿Qué pasaría si pudieras reanudar la función donde la dejaste? Esto es lo que proporcionan los generadores; se puede pensar en ellos como funciones reanudables.

Este es el ejemplo más sencillo de una función generadora:

def generate_ints(N):
    for i in range(N):
        yield i

Se ha introducido una nueva palabra clave, yield, para los generadores. Cualquier función que contenga una declaración yield es una función generadora; esto es detectado por el compilador de código de bits de Python que compila la función especialmente como resultado.

Cuando se llama a una función generadora, ésta no retorna un único valor, sino que retorna un objeto generador que soporta el protocolo de los iteradores. Al ejecutar la sentencia yield, el generador retorna el valor de i, de forma similar a una sentencia return. La gran diferencia entre yield y una sentencia return es que al llegar a una sentencia yield se suspende el estado de ejecución del generador y se conservan las variables locales. En la siguiente llamada al método .next() del generador, la función se reanudará la ejecución inmediatamente después de la sentencia yield. (Por razones complicadas, la sentencia yield no está permitida dentro del bloque try de una sentencia try…`; lea PEP 255 para una explicación completa de la interacción entre yield y las excepciones)

Este es un ejemplo de uso del generador generate_ints():

>>> gen = generate_ints(3)
>>> gen
<generator object at 0x8117f90>
>>> gen.next()
0
>>> gen.next()
1
>>> gen.next()
2
>>> gen.next()
Traceback (most recent call last):
  File "stdin", line 1, in ?
  File "stdin", line 2, in generate_ints
StopIteration

También podrías escribir for i in generate_ints(5), o a,b,c = generate_ints(3).

Dentro de una función generadora, la expresión return sólo puede usarse sin un valor, y señala el final de la procesión de valores; después el generador no puede retornar más valores. return con un valor, como return 5, es un error de sintaxis dentro de una función generadora. El final de los resultados del generador también puede indicarse levantando manualmente StopIteration, o simplemente dejando que el flujo de ejecución caiga en el fondo de la función.

Puedes conseguir el efecto de los generadores manualmente escribiendo tu propia clase y almacenando todas las variables locales del generador como variables de instancia. Por ejemplo, la devolución de una lista de enteros podría hacerse estableciendo self.count a 0, y haciendo que el método next() incremente self.count y lo retorne. Sin embargo, para un generador medianamente complicado, escribir la clase correspondiente sería mucho más complicado. Lib/test/test_generators.py contiene varios ejemplos más interesantes. El más sencillo implementa un recorrido en orden de un árbol utilizando generadores de forma recursiva

# A recursive generator that generates Tree leaves in in-order.
def inorder(t):
    if t:
        for x in inorder(t.left):
            yield x
        yield t.label
        for x in inorder(t.right):
            yield x

Otros dos ejemplos en Lib/test/test_generators.py producen soluciones para el problema de las N reinas (colocar $N$ reinas en un tablero de ajedrez $NxN$ de forma que ninguna reina amenace a otra) y el recorrido del caballero (una ruta que lleva a un caballo a cada casilla de un tablero de ajedrez $NxN$ sin visitar ninguna casilla dos veces).

La idea de los generadores proviene de otros lenguajes de programación, especialmente de Icon (https://www.cs.arizona.edu/icon/), donde la idea de los generadores es fundamental. En Icon, cada expresión y llamada a una función se comporta como un generador. Un ejemplo de «An Overview of the Icon Programming Language» en https://www.cs.arizona.edu/icon/docs/ipd266.htm da una idea de cómo es esto:

sentence := "Store it in the neighboring harbor"
if (i := find("or", sentence)) > 5 then write(i)

En Icon la función find() retorna los índices en los que se encuentra la subcadena «o»: 3, 23, 33. En la expresión if, a i se le asigna primero un valor de 3, pero 3 es menor que 5, por lo que la comparación falla, e Icon la reintenta con el segundo valor de 23. 23 es mayor que 5, por lo que la comparación ahora tiene éxito, y el código imprime el valor 23 en la pantalla.

Python no va tan lejos como Icon en la adopción de generadores como concepto central. Los generadores se consideran parte del núcleo del lenguaje Python, pero aprenderlos o utilizarlos no es obligatorio; si no resuelven ningún problema que tengas, siéntete libre de ignorarlos. Una característica novedosa de la interfaz de Python en comparación con la de Icon es que el estado de un generador se representa como un objeto concreto (el iterador) que puede pasarse a otras funciones o almacenarse en una estructura de datos.

Ver también

PEP 255 - Generadores simples

Escrito por Neil Schemenauer, Tim Peters, Magnus Lie Hetland. Implementado principalmente por Neil Schemenauer y Tim Peters, con otras correcciones del equipo de Python Labs.

PEP 263: Codificación del código fuente

Los archivos fuente de Python ahora pueden declararse con diferentes codificaciones de conjuntos de caracteres. Las codificaciones se declaran incluyendo un comentario con formato especial en la primera o segunda línea del archivo fuente. Por ejemplo, un archivo UTF-8 puede declararse con:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

Sin esta declaración de codificación, la codificación por defecto utilizada es ASCII de 7 bits. Ejecutar o importar módulos que contengan literales de cadena con caracteres de 8 bits y que no tengan una declaración de codificación dará lugar a un DeprecationWarning señalado por Python 2.3; en 2.4 será un error de sintaxis.

La declaración de codificación sólo afecta a los literales de cadena Unicode, que se convertirán a Unicode utilizando la codificación especificada. Ten en cuenta que los identificadores de Python siguen restringidos a caracteres ASCII, por lo que no puedes tener nombres de variables que utilicen caracteres fuera de los alfanuméricos habituales.

Ver también

PEP 263 - Definición de las codificaciones del código fuente de Python

Escrito por Marc-André Lemburg y Martin von Löwis; realizado por Suzuki Hisao y Martin von Löwis.

PEP 273: Importar módulos desde archivos ZIP

El nuevo módulo zipimport añade soporte para importar módulos desde un archivo en formato ZIP. No es necesario importar el módulo explícitamente; se importará automáticamente si se añade el nombre de un archivo ZIP a sys.path. Por ejemplo:

amk@nyman:~/src/python$ unzip -l /tmp/example.zip
Archive:  /tmp/example.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
     8467  11-26-02 22:30   jwzthreading.py
 --------                   -------
     8467                   1 file
amk@nyman:~/src/python$ ./python
Python 2.3 (#1, Aug 1 2003, 19:54:32)
>>> import sys
>>> sys.path.insert(0, '/tmp/example.zip')  # Add .zip file to front of path
>>> import jwzthreading
>>> jwzthreading.__file__
'/tmp/example.zip/jwzthreading.py'
>>>

Una entrada en sys.path puede ser ahora el nombre de un archivo ZIP. El archivo ZIP puede contener cualquier tipo de ficheros, pero sólo se pueden importar los ficheros llamados *.py, *.pyc, o *.pyo. Si un archivo sólo contiene ficheros *.py, Python no intentará modificar el archivo añadiendo el correspondiente fichero *.pyc, lo que significa que si un archivo ZIP no contiene ficheros *.pyc, la importación puede ser bastante lenta.

También se puede especificar una ruta dentro del archivo para importar sólo de un subdirectorio; por ejemplo, la ruta /tmp/example.zip/lib/ sólo importaría del subdirectorio lib/ dentro del archivo.

Ver también

PEP 273 - Importación de módulos desde archivos Zip

Escrito por James C. Ahlstrom, que también proporcionó una implementación. Python 2.3 sigue la especificación en PEP 273, pero utiliza una implementación escrita por Just van Rossum que utiliza los ganchos de importación descritos en PEP 302. Vea la sección PEP 302: Nuevos ganchos de importación para una descripción de los nuevos ganchos de importación.

PEP 277: Soporte de nombres de archivo Unicode para Windows NT

En Windows NT, 2000 y XP, el sistema almacena los nombres de archivo como cadenas Unicode. Tradicionalmente, Python ha representado los nombres de archivo como cadenas de bytes, lo cual es inadecuado porque hace que algunos nombres de archivo sean inaccesibles.

Python permite ahora utilizar cadenas Unicode arbitrarias (dentro de las limitaciones del sistema de archivos) para todas las funciones que esperan nombres de archivos, sobre todo la función incorporada open(). Si se pasa una cadena Unicode a os.listdir(), Python retorna ahora una lista de cadenas Unicode. Una nueva función, os.getcwdu(), retorna el directorio actual como una cadena Unicode.

Las cadenas de bytes siguen funcionando como nombres de archivo, y en Windows Python las convertirá de forma transparente a Unicode utilizando la codificación mbcs.

Otros sistemas también permiten cadenas Unicode como nombres de archivo, pero las convierten en cadenas de bytes antes de pasarlas al sistema, lo que puede provocar un UnicodeError. Las aplicaciones pueden comprobar si se admiten cadenas Unicode arbitrarias como nombres de archivo comprobando os.path.supports_unicode_filenames, un valor booleano.

En MacOS, os.listdir() ahora puede retornar nombres de archivo Unicode.

Ver también

PEP 277 - Soporte de nombres de archivo Unicode para Windows NT

Escrito por Neil Hodgson; realizado por Neil Hodgson, Martin von Löwis y Mark Hammond.

PEP 278: Soporte universal de nuevas líneas

Los tres principales sistemas operativos que se utilizan hoy en día son Microsoft Windows, el sistema operativo Macintosh de Apple y los diversos derivados de Unix. Una pequeña molestia del trabajo entre plataformas es que estas tres plataformas utilizan diferentes caracteres para marcar el final de las líneas en los archivos de texto. Unix utiliza el salto de línea (carácter ASCII 10), MacOS utiliza el retorno de carro (carácter ASCII 13), y Windows utiliza una secuencia de dos caracteres de un retorno de carro más una nueva línea.

Los objetos de archivo de Python pueden ahora soportar convenciones de fin de línea distintas de la que sigue la plataforma en la que se ejecuta Python. Al abrir un archivo con el modo 'U o 'rU se abrirá un archivo para su lectura en modo universal newlines. Las tres convenciones de final de línea se traducirán a un '\n' en las cadenas retornadas por los distintos métodos de archivo como read() y readline().

El soporte universal de nuevas líneas también se utiliza al importar módulos y al ejecutar un archivo con la función execfile(). Esto significa que los módulos de Python pueden ser compartidos entre los tres sistemas operativos sin necesidad de convertir los finales de línea.

Esta función puede desactivarse al compilar Python especificando la opción --without-universal-newlines al ejecutar el script configure de Python.

Ver también

PEP 278 - Soporte universal de nuevas líneas

Escrito y ejecutado por Jack Jansen.

PEP 279: enumerate()

Una nueva función incorporada, enumerate(), hará que ciertos bucles sean un poco más claros. enumerate(cosa), donde cosa es un iterador o una secuencia, retorna un iterador que retornará (0, cosa[0]), (1, cosa[1]), (2, cosa[2]), y así sucesivamente.

Un modismo común para cambiar cada elemento de una lista tiene el siguiente aspecto:

for i in range(len(L)):
    item = L[i]
    # ... compute some result based on item ...
    L[i] = result

Esto se puede reescribir usando enumerate() como:

for i, item in enumerate(L):
    # ... compute some result based on item ...
    L[i] = result

Ver también

PEP 279 - La función incorporada enumerate()

Escrito y ejecutado por Raymond D. Hettinger.

PEP 282: El paquete de registro

Se ha añadido a Python 2.3 un paquete estándar para escribir registros, logging. Proporciona un mecanismo potente y flexible para generar salidas de registro que pueden ser filtradas y procesadas de varias maneras. Se puede utilizar un archivo de configuración escrito en un formato estándar para controlar el comportamiento de registro de un programa. Python incluye manejadores que escribirán los registros en el error estándar o en un archivo o socket, los enviarán al registro del sistema, o incluso los enviarán por correo electrónico a una dirección particular; por supuesto, también es posible escribir tus propias clases de manejadores.

La clase Logger es la clase principal. La mayoría del código de la aplicación tratará con uno o más objetos Logger, cada uno utilizado por un subsistema particular de la aplicación. Cada Logger se identifica con un nombre, y los nombres se organizan en una jerarquía utilizando . como separador de componentes. Por ejemplo, puedes tener instancias de Logger llamadas servidor, servidor.auth y servidor.network. Estas dos últimas instancias están por debajo de servidor en la jerarquía. Esto significa que si aumentas la verbosidad de servidor o diriges los mensajes de servidor a un gestor diferente, los cambios también se aplicarán a los registros de servidor.auth y servidor.network. También hay un Logger raíz que es el padre de todos los demás loggers.

Para usos sencillos, el paquete logging contiene algunas funciones de conveniencia que siempre utilizan la raíz log:

import logging

logging.debug('Debugging information')
logging.info('Informational message')
logging.warning('Warning:config file %s not found', 'server.conf')
logging.error('Error occurred')
logging.critical('Critical error -- shutting down')

Esto produce la siguiente salida:

WARNING:root:Warning:config file server.conf not found
ERROR:root:Error occurred
CRITICAL:root:Critical error -- shutting down

En la configuración por defecto, los mensajes informativos y de depuración se suprimen y la salida se envía al error estándar. Puede habilitar la visualización de mensajes informativos y de depuración llamando al método setLevel() del registrador raíz.

Observe que la llamada warning() utiliza operadores de formato de cadena; todas las funciones para el registro de mensajes toman los argumentos (msg, arg1, arg2, ...) y registran la cadena resultante de msg % (arg1, arg2, ...).

También hay una función exception() que registra el rastro más reciente. Cualquiera de las otras funciones también registrará el rastro si se especifica un valor verdadero para el argumento de la palabra clave exc_info.

def f():
    try:    1/0
    except: logging.exception('Problem recorded')

f()

Esto produce la siguiente salida:

ERROR:root:Problem recorded
Traceback (most recent call last):
  File "t.py", line 6, in f
    1/0
ZeroDivisionError: integer division or modulo by zero

Los programas un poco más avanzados utilizarán un logger distinto del logger raíz. La función getLogger(nombre) se utiliza para obtener un registro en particular, creándolo si aún no existe. getLogger(None) retorna el logger raíz.

log = logging.getLogger('server')
 ...
log.info('Listening on port %i', port)
 ...
log.critical('Disk full')
 ...

Los registros se suelen propagar hacia arriba en la jerarquía, por lo que un mensaje registrado en servidor.auth también es visto por servidor y root, pero un Logger puede evitar esto estableciendo su atributo propagate a False.

Hay más clases proporcionadas por el paquete logging que pueden ser personalizadas. Cuando una instancia de Logger recibe la orden de registrar un mensaje, crea una instancia de LogRecord que se envía a cualquier número de instancias de Handler diferentes. Los loggers y handlers también pueden tener una lista adjunta de filtros, y cada filtro puede hacer que el LogRecord sea ignorado o puede modificar el registro antes de pasarlo. Cuando finalmente se emiten, las instancias de LogRecord se convierten en texto mediante una clase Formatter. Todas estas clases pueden ser reemplazadas por tus propias clases especialmente escritas.

Con todas estas características, el paquete logging debería proporcionar suficiente flexibilidad incluso para las aplicaciones más complicadas. Esto es sólo un resumen incompleto de sus características, así que por favor consulte la documentación de referencia del paquete para todos los detalles. La lectura de PEP 282 también será útil.

Ver también

PEP 282 - Un sistema de registro

Escrito por Vinay Sajip y Trent Mick; implementado por Vinay Sajip.

PEP 285: Un tipo booleano

Se ha añadido un tipo booleano a Python 2.3. Se añadieron dos nuevas constantes al módulo __builtin__, True y False. (Las constantes True y False se añadieron a los módulos incorporados en Python 2.2.1, pero las versiones de 2.2.1 se ajustan simplemente a valores enteros de 1 y 0 y no son un tipo diferente)

El objeto de tipo para este nuevo tipo se denomina bool; su constructor toma cualquier valor de Python y lo convierte en True o False.

>>> bool(1)
True
>>> bool(0)
False
>>> bool([])
False
>>> bool( (1,) )
True

La mayoría de los módulos de la biblioteca estándar y las funciones incorporadas se han modificado para retornar booleanos.

>>> obj = []
>>> hasattr(obj, 'append')
True
>>> isinstance(obj, list)
True
>>> isinstance(obj, tuple)
False

Los booleanos de Python se añadieron con el objetivo principal de hacer el código más claro. Por ejemplo, si estás leyendo una función y te encuentras con la sentencia return 1, podrías preguntarte si el 1 representa un valor de verdad booleano, un índice o un coeficiente que multiplica alguna otra cantidad. Sin embargo, si la sentencia es return True, el significado del valor de retorno es bastante claro.

Los booleanos de Python no se añadieron en aras de una comprobación de tipos estricta. Un lenguaje muy estricto como Pascal también le impediría realizar aritmética con booleanos, y requeriría que la expresión en una declaración if siempre se evaluara a un resultado booleano. Python no es tan estricto y nunca lo será, como dice explícitamente PEP 285. Esto significa que puede utilizar cualquier expresión en una sentencia if, incluso las que se evalúan a una lista o tupla o algún objeto aleatorio. El tipo Booleano es una subclase de la clase int por lo que la aritmética que utiliza un Booleano sigue funcionando.

>>> True + 1
2
>>> False + 1
1
>>> False * 75
0
>>> True * 75
75

Para resumir True and False en una frase: son formas alternativas de deletrear los valores enteros 1 y 0, con la única diferencia de que str() y repr() retornan las cadenas Verdadero y Falso en lugar de 1 y 0.

Ver también

PEP 285 - Añadir un tipo booleano

Escrito y ejecutado por GvR.

PEP 293: Llamadas de retorno para el manejo de errores del códec

Al codificar una cadena Unicode en una cadena de bytes, pueden encontrarse caracteres no codificables. Hasta ahora, Python ha permitido especificar el procesamiento del error como «estricto» (lanzando UnicodeError), «ignorar» (saltando el carácter), o «reemplazar» (usando un signo de interrogación en la cadena de salida), siendo «estricto» el comportamiento por defecto. Puede ser deseable especificar un procesamiento alternativo de tales errores, como insertar una referencia de carácter XML o una referencia de entidad HTML en la cadena convertida.

Python tiene ahora un marco flexible para añadir diferentes estrategias de procesamiento. Se pueden añadir nuevos manejadores de errores con codecs.register_error(), y los códecs pueden acceder al manejador de errores con codecs.lookup_error(). Se ha añadido una API en C equivalente para los códecs escritos en C. El gestor de errores obtiene la información de estado necesaria, como la cadena que se está convirtiendo, la posición en la cadena donde se ha detectado el error y la codificación de destino. El controlador puede entonces lanzar una excepción o retornar una cadena de reemplazo.

Se han implementado dos manejadores de error adicionales utilizando este marco: «backslashreplace» utiliza las comillas de barra invertida de Python para representar los caracteres no codificables y «xmlcharrefreplace» emite referencias de caracteres XML.

Ver también

PEP 293 - Retrollamadas de manejo de errores del códec

Escrito y ejecutado por Walter Dörwald.

PEP 301: Índice de paquetes y metadatos para Distutils

La compatibilidad con el catálogo de Python, largamente solicitada, hace su primera aparición en 2.3.

El corazón del catálogo es el nuevo comando register de Distutils. Ejecutando python setup.py register se recogen los metadatos que describen un paquete, como su nombre, versión, mantenedor, descripción, etc., y se envían a un servidor de catálogo central. El catálogo resultante está disponible en https://pypi.org.

Para hacer el catálogo un poco más útil, se ha añadido un nuevo argumento opcional de palabra clave clasificadores a la función Distutils setup(). Se puede suministrar una lista de cadenas de estilo Trove para ayudar a clasificar el software.

Aquí hay un ejemplo setup.py con clasificadores, escrito para que sea compatible con las versiones más antiguas de Distutils:

from distutils import core
kw = {'name': "Quixote",
      'version': "0.5.1",
      'description': "A highly Pythonic Web application framework",
      # ...
      }

if (hasattr(core, 'setup_keywords') and
    'classifiers' in core.setup_keywords):
    kw['classifiers'] = \
        ['Topic :: Internet :: WWW/HTTP :: Dynamic Content',
         'Environment :: No Input/Output (Daemon)',
         'Intended Audience :: Developers'],

core.setup(**kw)

La lista completa de clasificadores se puede obtener ejecutando python setup.py register --list-classifiers.

Ver también

PEP 301 - Índice de paquetes y metadatos para Distutils

Escrito y ejecutado por Richard Jones.

PEP 302: Nuevos ganchos de importación

Aunque ha sido posible escribir ganchos de importación personalizados desde que se introdujo el módulo ihooks en Python 1.3, nadie ha estado nunca realmente contento con él porque escribir nuevos ganchos de importación es difícil y complicado. Se han propuesto varias alternativas, como los módulos imputil y iu, pero ninguno de ellos ha tenido mucha aceptación, y ninguno era fácilmente utilizable desde el código C.

PEP 302 toma prestadas ideas de sus predecesores, especialmente del módulo iu de Gordon McMillan. Se añaden tres nuevos elementos al módulo sys:

  • sys.path_hooks es una lista de objetos invocables; la mayoría de las veces serán clases. Cada llamada toma una cadena que contiene una ruta y retorna un objeto importador que manejará las importaciones desde esta ruta o lanza una excepción ImportError si no puede manejar esta ruta.

  • sys.path_importer_cache almacena en caché los objetos del importador para cada ruta, por lo que sys.path_hooks sólo tendrá que ser recorrido una vez para cada ruta.

  • sys.meta_path es una lista de objetos importadores que se recorrerán antes de comprobar sys.path. Esta lista está inicialmente vacía, pero el código de usuario puede añadir objetos a ella. Los módulos adicionales incorporados y congelados pueden ser importados por un objeto añadido a esta lista.

Los objetos importadores deben tener un único método, find_module(fullname, path=None). fullname será un nombre de módulo o paquete, por ejemplo string o distutils.core. find_module() debe retornar un objeto cargador que tenga un único método, load_module(fullname), que cree y retorne el objeto módulo correspondiente.

Por lo tanto, el pseudocódigo de la nueva lógica de importación de Python es algo así (simplificado un poco; véase PEP 302 para los detalles completos):

for mp in sys.meta_path:
    loader = mp(fullname)
    if loader is not None:
        <module> = loader.load_module(fullname)

for path in sys.path:
    for hook in sys.path_hooks:
        try:
            importer = hook(path)
        except ImportError:
            # ImportError, so try the other path hooks
            pass
        else:
            loader = importer.find_module(fullname)
            <module> = loader.load_module(fullname)

# Not found!
raise ImportError

Ver también

PEP 302 - Nuevos ganchos de importación

Escrito por Just van Rossum y Paul Moore. Implementado por Just van Rossum.

PEP 305: Archivos separados por comas

Los archivos separados por comas son un formato frecuentemente utilizado para exportar datos de bases de datos y hojas de cálculo. Python 2.3 añade un analizador de archivos separados por comas.

El formato separado por comas es engañosamente sencillo a primera vista:

Costs,150,200,3.95

Leer una línea y llamar a line.split(','): ¿qué puede ser más sencillo? Pero si se añaden datos de cadena que pueden contener comas, las cosas se complican:

"Costs",150,200,3.95,"Includes taxes, shipping, and sundry items"

Una expresión regular grande y fea puede analizar esto, pero usar el nuevo paquete csv es mucho más sencillo:

import csv

input = open('datafile', 'rb')
reader = csv.reader(input)
for line in reader:
    print line

La función reader() admite varias opciones. El separador de campos no se limita a la coma y puede cambiarse por cualquier carácter, al igual que las comillas y el final de línea.

Se pueden definir y registrar diferentes dialectos de archivos separados por comas; actualmente hay dos dialectos, ambos utilizados por Microsoft Excel. Una clase csv.writer independiente generará archivos separados por comas a partir de una sucesión de tuplas o listas, citando cadenas que contengan el delimitador.

Ver también

PEP 305 - API de archivos CSV

Escrito y realizado por Kevin Altis, Dave Cole, Andrew McNamara, Skip Montanaro, Cliff Wells.

PEP 307: Mejoras en Pickle

Los módulos pickle y cPickle recibieron cierta atención durante el ciclo de desarrollo de la 2.3. En 2.2, las clases de estilo nuevo podían ser desempaquetadas sin dificultad, pero no se desempaquetaba de forma muy compacta; PEP 307 cita un ejemplo trivial en el que una clase de estilo nuevo da lugar a una cadena desempaquetada tres veces más larga que la de una clase clásica.

La solución fue inventar un nuevo protocolo pickle. La función pickle.dumps() soporta desde hace tiempo una bandera de texto o binario. En la versión 2.3, esta bandera se ha redefinido, pasando de ser un booleano a un entero: 0 es el antiguo formato pickle en modo texto, 1 es el antiguo formato binario, y ahora 2 es un nuevo formato específico de 2.3. Una nueva constante, pickle.HIGHEST_PROTOCOL, puede utilizarse para seleccionar el protocolo más elegante disponible.

El unpickling ya no se considera una operación segura. El pickle de la versión 2.2 proporcionaba ganchos para tratar de evitar que las clases no seguras fueran deserializadas (específicamente, un atributo __safe_for_unpickling__), pero nada de este código fue nunca auditado y por lo tanto todo ha sido eliminado en la versión 2.3. No se debe deserializar datos no confiables en ninguna versión de Python.

Para reducir la sobrecarga de pickling de las clases de estilo nuevo, se ha añadido una nueva interfaz para personalizar el pickling mediante tres métodos especiales: __getstate__(), __setstate__(), y __getnewargs__(). Consulte PEP 307 para conocer la semántica completa de estos métodos.

Como forma de comprimir aún más los pickles, ahora es posible utilizar códigos enteros en lugar de cadenas largas para identificar las clases serializadas. La Python Software Foundation mantendrá una lista de códigos estandarizados; también hay una gama de códigos para uso privado. Actualmente no se ha especificado ningún código.

Ver también

PEP 307 - Extensiones del protocolo pickle

Escrito y ejecutado por Guido van Rossum y Tim Peters.

Rebanadas ampliadas

Desde la versión 1.4 de Python, la sintaxis de corte admite un tercer argumento opcional «paso» o «zancada». Por ejemplo, estas son todas las sintaxis legales de Python: L[1:10:2], L[:-1:1], L[::-1]. Esto se añadió a Python a petición de los desarrolladores de Numerical Python, que utiliza ampliamente el tercer argumento. Sin embargo, los tipos de secuencias de listas, tuplas y cadenas incorporados en Python nunca han soportado esta característica, y lanzan un TypeError si lo intentas. Michael Hudson ha contribuido con un parche para solucionar este problema.

Por ejemplo, ahora puede extraer fácilmente los elementos de una lista que tengan índices pares:

>>> L = range(10)
>>> L[::2]
[0, 2, 4, 6, 8]

Los valores negativos también sirven para hacer una copia de la misma lista en orden inverso:

>>> L[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Esto también funciona para tuplas, arrays y cadenas:

>>> s='abcd'
>>> s[::2]
'ac'
>>> s[::-1]
'dcba'

Si tienes una secuencia mutable, como una lista o un array, puedes asignar o eliminar una rebanada extendida, pero hay algunas diferencias entre la asignación a rebanadas extendidas y regulares. La asignación a una rebanada regular se puede utilizar para cambiar la longitud de la secuencia:

>>> a = range(3)
>>> a
[0, 1, 2]
>>> a[1:3] = [4, 5, 6]
>>> a
[0, 4, 5, 6]

Las rebanadas extendidas no son tan flexibles. Cuando se asigna a una rebanada extendida, la lista a la derecha de la declaración debe contener el mismo número de elementos que la rebanada que está reemplazando:

>>> a = range(4)
>>> a
[0, 1, 2, 3]
>>> a[::2]
[0, 2]
>>> a[::2] = [0, -1]
>>> a
[0, 1, -1, 3]
>>> a[::2] = [0,1,2]
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: attempt to assign sequence of size 3 to extended slice of size 2

La eliminación es más sencilla:

>>> a = range(4)
>>> a
[0, 1, 2, 3]
>>> a[::2]
[0, 2]
>>> del a[::2]
>>> a
[1, 3]

Ahora también se pueden pasar objetos slice a los métodos __getitem__() de las secuencias incorporadas:

>>> range(10).__getitem__(slice(0, 5, 2))
[0, 2, 4]

O utilizar los objetos de corte directamente en los subíndices:

>>> range(10)[slice(0, 5, 2)]
[0, 2, 4]

Para simplificar la implementación de secuencias que soportan el corte extendido, los objetos slice tienen ahora un método indices(length) que, dada la longitud de una secuencia, retorna una tupla (start, stop, step) que puede pasarse directamente a range(). indices() maneja los índices omitidos y los que están fuera de los límites de una manera consistente con los slices regulares (¡y esta frase inocua esconde un montón de detalles confusos!). El método está pensado para ser utilizado así:

class FakeSeq:
    ...
    def calc_item(self, i):
        ...
    def __getitem__(self, item):
        if isinstance(item, slice):
            indices = item.indices(len(self))
            return FakeSeq([self.calc_item(i) for i in range(*indices)])
        else:
            return self.calc_item(i)

En este ejemplo también se puede ver que el objeto incorporado slice es ahora el objeto tipo para el tipo slice, y ya no es una función. Esto es consistente con Python 2.2, donde int, str, etc., sufrieron el mismo cambio.

Otros cambios en el lenguaje

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

  • La expresión yield es ahora siempre una palabra clave, como se describe en la sección PEP 255: Generadores simples de este documento.

  • Se ha añadido una nueva función incorporada enumerate(), como se describe en la sección PEP 279: enumerate() de este documento.

  • Se han añadido dos nuevas constantes, True y False junto con el tipo incorporado bool, como se describe en la sección PEP 285: Un tipo booleano de este documento.

  • El constructor de tipo int() ahora retornará un entero largo en lugar de lanzar un OverflowError cuando una cadena o un número de punto flotante es demasiado grande para caber en un entero. Esto puede llevar al resultado paradójico de que isinstance(int(expresión), int) sea falso, pero parece poco probable que cause problemas en la práctica.

  • Los tipos incorporados ahora soportan la sintaxis de rebanado extendida, como se describe en la sección Rebanadas ampliadas de este documento.

  • Una nueva función incorporada, suma(iterable, start=0), suma los elementos numéricos en el objeto iterable y retorna su suma. suma() sólo acepta números, lo que significa que no se puede utilizar para concatenar un montón de cadenas. (Contribución de Alex Martelli)

  • list.insert(pos, valor) solía insertar valor al principio de la lista cuando pos era negativo. El comportamiento ha sido cambiado para ser consistente con la indexación de las rebanadas, así que cuando pos es -1 el valor será insertado antes del último elemento, y así sucesivamente.

  • list.index(value), que busca valor dentro de la lista y retorna su índice, ahora toma los argumentos opcionales start y stop para limitar la búsqueda sólo a una parte de la lista.

  • Los diccionarios tienen un nuevo método, pop(key[, *default*]), que retorna el valor correspondiente a key y elimina ese par clave/valor del diccionario. Si la clave solicitada no está presente en el diccionario, se retorna default si está especificada y se lanza KeyError si no lo está:

    >>> d = {1:2}
    >>> d
    {1: 2}
    >>> d.pop(4)
    Traceback (most recent call last):
      File "stdin", line 1, in ?
    KeyError: 4
    >>> d.pop(1)
    2
    >>> d.pop(1)
    Traceback (most recent call last):
      File "stdin", line 1, in ?
    KeyError: 'pop(): dictionary is empty'
    >>> d
    {}
    >>>
    

    También hay un nuevo método de clase, dict.fromkeys(iterable, value), que crea un diccionario con claves tomadas del iterador iterable suministrado y todos los valores establecidos a value, por defecto a None.

    (Parches aportados por Raymond Hettinger)

    Además, el constructor dict() ahora acepta argumentos de palabras clave para simplificar la creación de pequeños diccionarios:

    >>> dict(red=1, blue=2, green=3, black=4)
    {'blue': 2, 'black': 4, 'green': 3, 'red': 1}
    

    (Contribución de Just van Rossum.)

  • La expresión assert ya no comprueba la bandera debug__, por lo que ya no se pueden desactivar las aserciones asignando a __debug__. Ejecutar Python con la opción -O seguirá generando código que no ejecute ninguna aserción.

  • La mayoría de los objetos de tipo son ahora invocables, por lo que puedes usarlos para crear nuevos objetos como funciones, clases y módulos. (Esto significa que el módulo new puede quedar obsoleto en una futura versión de Python, porque ahora puedes utilizar los objetos de tipo disponibles en el módulo types) Por ejemplo, puede crear un nuevo objeto de módulo con el siguiente código:

    >>> import types
    >>> m = types.ModuleType('abc','docstring')
    >>> m
    <module 'abc' (built-in)>
    >>> m.__doc__
    'docstring'
    
  • Se ha añadido una nueva advertencia, PendingDeprecationWarning para indicar las características que están en proceso de ser obsoletas. La advertencia no se imprimirá por defecto. Para comprobar el uso de funciones que quedarán obsoletas en el futuro, proporcione -Walways::PendingDeprecationWarning:: en la línea de comandos o utilice warnings.filterwarnings().

  • Ha comenzado el proceso de desaprobación de las excepciones basadas en cadenas, como en lanzamiento de "Error ocurred”. Al lanzar una cadena, ahora se activará PendingDeprecationWarning.

  • El uso de None como nombre de una variable ahora resultará en una advertencia SyntaxWarning. En una futura versión de Python, None podría convertirse en una palabra clave.

  • El método xreadlines() de los objetos archivo, introducido en Python 2.1, ya no es necesario porque los archivos se comportan ahora como su propio iterador. xreadlines() se introdujo originalmente como una forma más rápida de recorrer todas las líneas de un archivo, pero ahora se puede escribir simplemente for line in file_obj. Los objetos archivo también tienen un nuevo atributo encoding de sólo lectura que proporciona la codificación utilizada por el archivo; las cadenas Unicode escritas en el archivo se convertirán automáticamente a bytes utilizando la codificación dada.

  • El orden de resolución de los métodos utilizados por las clases del nuevo estilo ha cambiado, aunque sólo notarás la diferencia si tienes una jerarquía de herencia realmente complicada. Las clases clásicas no se ven afectadas por este cambio. Python 2.2 originalmente utilizaba una ordenación topológica de los ancestros de una clase, pero 2.3 ahora utiliza el algoritmo C3 como se describe en el artículo «A Monotonic Superclass Linearization for Dylan». Para entender la motivación de este cambio, lea el artículo de Michele Simionato «Python 2.3 Method Resolution Order», o lea el hilo en python-dev que comienza con el mensaje en https://mail.python.org/pipermail/python-dev/2002-October/029035.html. Samuele Pedroni fue el primero en señalar el problema y también implementó la solución codificando el algoritmo C3.

  • Python ejecuta programas multihilo cambiando entre hilos después de ejecutar N bytecodes. El valor por defecto de N se ha incrementado de 10 a 100 bytecodes, acelerando las aplicaciones de un solo hilo al reducir la sobrecarga de cambio. Algunas aplicaciones multihilo pueden sufrir un tiempo de respuesta más lento, pero eso se arregla fácilmente estableciendo el límite a un número menor usando sys.setcheckinterval(N). El límite puede recuperarse con la nueva función sys.getcheckinterval().

  • Un cambio menor pero de gran alcance es que los nombres de los tipos de extensión definidos por los módulos incluidos con Python ahora contienen el módulo y un .' delante del nombre del tipo. Por ejemplo, en Python 2.2, si creabas un socket e imprimías su __class__, obtendrías esta salida:

    >>> s = socket.socket()
    >>> s.__class__
    <type 'socket'>
    

    En 2.3, se obtiene esto:

    >>> s.__class__
    <type '_socket.socket'>
    
  • Se ha eliminado una de las incompatibilidades señaladas entre las clases de estilo antiguo y las de estilo nuevo: ahora se pueden asignar a los atributos __name__ y __bases__ de las clases de estilo nuevo. Hay algunas restricciones sobre lo que se puede asignar a __bases__ en la línea de las relacionadas con la asignación al atributo __class__ de una instancia.

Cambios en las cadenas de texto

  • El operador in ahora funciona de forma diferente para las cadenas. Antes, cuando se evaluaba X en Y donde X y Y eran cadenas, X sólo podía ser un único carácter. Esto ha cambiado; X puede ser una cadena de cualquier longitud, y X en Y retornará True si X es una subcadena de Y. Si X es una cadena vacía, el resultado es siempre True.

    >>> 'ab' in 'abcd'
    True
    >>> 'ad' in 'abcd'
    False
    >>> '' in 'abcd'
    True
    

    Tenga en cuenta que esto no le dice dónde empieza la subcadena; si necesita esa información, utilice el método find() string.

  • Los métodos de cadena strip(), lstrip() y rstrip() tienen ahora un argumento opcional para especificar los caracteres a eliminar. El valor por defecto sigue siendo eliminar todos los caracteres de espacio en blanco:

    >>> '   abc '.strip()
    'abc'
    >>> '><><abc<><><>'.strip('<>')
    'abc'
    >>> '><><abc<><><>\n'.strip('<>')
    'abc<><><>\n'
    >>> u'\u4000\u4001abc\u4000'.strip(u'\u4000')
    u'\u4001abc'
    >>>
    

    (Sugerido por Simon Brunning y aplicado por Walter Dörwald)

  • Los métodos de cadena startswith() y endswith() ahora aceptan números negativos para los parámetros start y end.

  • Otro nuevo método de cadena es zfill(), originalmente una función del módulo string. zfill() rellena una cadena numérica con ceros a la izquierda hasta que tenga el ancho especificado. Tenga en cuenta que el operador % sigue siendo más flexible y potente que zfill().

    >>> '45'.zfill(4)
    '0045'
    >>> '12345'.zfill(4)
    '12345'
    >>> 'goofy'.zfill(6)
    '0goofy'
    

    (Contribución de Walter Dörwald.)

  • Se ha añadido un nuevo tipo de objeto, basestring. Tanto las cadenas de 8 bits como las cadenas Unicode heredan de este tipo, por lo que isinstance(obj, basestring) retornará True para cualquier tipo de cadena. Es un tipo completamente abstracto, por lo que no se pueden crear instancias de basestring.

  • Las cadenas internas ya no son inmortales y ahora serán recolectadas de la forma habitual cuando la única referencia a ellas sea desde el diccionario interno de cadenas internas. (Implementado por Oren Tirosh)

Optimizaciones

  • La creación de instancias de clases de estilo nuevo se ha hecho mucho más rápida; ¡ahora son más rápidas que las clases clásicas!

  • El método sort() de los objetos de la lista ha sido ampliamente reescrito por Tim Peters, y la implementación es significativamente más rápida.

  • La multiplicación de enteros largos es ahora mucho más rápida gracias a una implementación de la multiplicación Karatsuba, un algoritmo que escala mejor que el O(n*n) requerido para el algoritmo de multiplicación de la escuela primaria. (Parche original de Christopher A. Craig, y reelaborado significativamente por Tim Peters)

  • El opcode SET_LINENO ha desaparecido. Esto puede proporcionar un pequeño aumento de velocidad, dependiendo de la idiosincrasia de su compilador. Vea la sección Other Changes and Fixes para una explicación más larga. (Eliminado por Michael Hudson)

  • Los objetos xrange() tienen ahora su propio iterador, haciendo que for i in xrange(n) sea ligeramente más rápido que for i in range(n). (Parche de Raymond Hettinger)

  • Se han realizado una serie de pequeños reajustes en varios puntos conflictivos para mejorar el rendimiento, como por ejemplo alinear una función o eliminar algo de código. (Implementado principalmente por GvR, pero mucha gente ha contribuido con cambios individuales)

El resultado neto de las optimizaciones de la versión 2.3 es que Python 2.3 ejecuta el benchmark pystone alrededor de un 25% f más rápido que Python 2.2.

Módulos nuevos, mejorados y obsoletos

Como es habitual, la biblioteca estándar de Python ha recibido una serie de mejoras y correcciones de errores. Aquí hay una lista parcial de los cambios más notables, ordenados alfabéticamente por nombre de 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 CVS para obtener todos los detalles.

  • El módulo array soporta ahora matrices de caracteres Unicode que utilizan el carácter de formato 'u. Las matrices también soportan ahora el uso del operador de asignación += para añadir el contenido de otra matriz, y el operador de asignación *= para repetir una matriz. (Contribución de Jason Orendorff)

  • El módulo bsddb ha sido reemplazado por la versión 4.1.6 del paquete PyBSDDB, proporcionando una interfaz más completa para las características transaccionales de la biblioteca BerkeleyDB.

    La antigua versión del módulo ha sido renombrada como bsddb185 y ya no se construye automáticamente; tendrás que editar Modules/Setup para activarlo. Ten en cuenta que el nuevo paquete bsddb está pensado para ser compatible con el módulo antiguo, así que asegúrate de enviar errores si descubres alguna incompatibilidad. Al actualizar a Python 2.3, si el nuevo intérprete se compila con una nueva versión de la biblioteca BerkeleyDB subyacente, es casi seguro que tendrá que convertir sus archivos de base de datos a la nueva versión. Puede hacerlo fácilmente con los nuevos scripts db2pickle.py y pickle2db.py que encontrará en el directorio Tools/scripts de la distribución. Si ya ha estado utilizando el paquete PyBSDDB e importándolo como bsddb3, tendrá que cambiar sus sentencias import para importarlo como bsddb.

  • El nuevo módulo bz2 es una interfaz para la biblioteca de compresión de datos bz2. Los datos comprimidos con bz2 suelen ser más pequeños que los correspondientes datos comprimidos con zlib. (Contribución de Gustavo Niemeyer)

  • Se ha añadido un conjunto de tipos de fecha/hora estándar en el nuevo módulo datetime. Consulte la siguiente sección para obtener más detalles.

  • La clase Distutils Extension soporta ahora un argumento constructor extra llamado depends para listar archivos fuente adicionales de los que depende una extensión. Esto permite a Distutils recompilar el módulo si se modifica alguno de los archivos de dependencia. Por ejemplo, si sampmodule.c incluye el fichero de cabecera sample.h, se crearía el objeto Extension así:

    ext = Extension("samp",
                    sources=["sampmodule.c"],
                    depends=["sample.h"])
    

    La modificación de sample.h haría que el módulo se recompilara. (Contribución de Jeremy Hylton)

  • Otros cambios menores en Distutils: ahora comprueba las variables de entorno CC, CFLAGS, CPP, LDFLAGS y CPPFLAGS, utilizándolas para anular los ajustes de la configuración de Python (contribución de Robert Weber).

  • Anteriormente el módulo doctest sólo buscaba casos de prueba en los docstrings de los métodos y funciones públicos, pero ahora también examina los privados. La función DocTestSuite() crea un objeto unittest.TestSuite a partir de un conjunto de pruebas doctest.

  • La nueva función gc.get_referents(object) retorna una lista de todos los objetos referenciados por object.

  • El módulo getopt ha ganado una nueva función, gnu_getopt(), que admite los mismos argumentos que la función getopt() existente, pero utiliza el modo de exploración al estilo GNU. La función getopt() existente deja de procesar las opciones tan pronto como se encuentra un argumento que no es una opción, pero en el modo GNU el procesamiento continúa, lo que significa que las opciones y los argumentos pueden mezclarse. Por ejemplo:

    >>> getopt.getopt(['-f', 'filename', 'output', '-v'], 'f:v')
    ([('-f', 'filename')], ['output', '-v'])
    >>> getopt.gnu_getopt(['-f', 'filename', 'output', '-v'], 'f:v')
    ([('-f', 'filename'), ('-v', '')], ['output'])
    

    (Contribución de Peter Åstrand.)

  • Los módulos grp, pwd y resource retornan ahora tuplas mejoradas:

    >>> import grp
    >>> g = grp.getgrnam('amk')
    >>> g.gr_name, g.gr_gid
    ('amk', 500)
    
  • El módulo gzip ahora puede manejar archivos de más de 2 GiB.

  • El nuevo módulo heapq contiene una implementación de un algoritmo de colas de montón. Un montón es una estructura de datos similar a un array que mantiene los elementos en un orden parcialmente ordenado de forma que, para cada índice k, heap[k] <= heap[2*k+1] y heap[k] <= heap[2*k+2]. Esto hace que sea rápido eliminar el elemento más pequeño, y la inserción de un nuevo elemento manteniendo la propiedad del montón es O(lg n). (Véase https://xlinux.nist.gov/dads//HTML/priorityque.html para más información sobre la estructura de datos de la cola de prioridad)

    El módulo heapq proporciona las funciones heappush() y heappop() para añadir y eliminar elementos manteniendo la propiedad del montón sobre algún otro tipo de secuencia mutable de Python. Aquí hay un ejemplo que utiliza una lista de Python:

    >>> import heapq
    >>> heap = []
    >>> for item in [3, 7, 5, 11, 1]:
    ...    heapq.heappush(heap, item)
    ...
    >>> heap
    [1, 3, 5, 11, 7]
    >>> heapq.heappop(heap)
    1
    >>> heapq.heappop(heap)
    3
    >>> heap
    [5, 7, 11]
    

    (Contribución de Kevin O’Connor.)

  • El entorno de desarrollo integrado IDLE ha sido actualizado utilizando el código del proyecto IDLEfork (http://idlefork.sourceforge.net). La característica más notable es que el código que se está desarrollando se ejecuta ahora en un subproceso, lo que significa que ya no es necesario realizar operaciones manuales de reload(). El código central de IDLE ha sido incorporado a la biblioteca estándar como el paquete idlelib.

  • The imaplib module now supports IMAP over SSL. (Contributed by Piers Lauder and Tino Lange.)

  • The itertools contains a number of useful functions for use with iterators, inspired by various functions provided by the ML and Haskell languages. For example, itertools.ifilter(predicate, iterator) returns all elements in the iterator for which the function predicate() returns True, and itertools.repeat(obj, N) returns obj N times. There are a number of other functions in the module; see the package’s reference documentation for details. (Contributed by Raymond Hettinger.)

  • Two new functions in the math module, degrees(rads) and radians(degs), convert between radians and degrees. Other functions in the math module such as math.sin() and math.cos() have always required input values measured in radians. Also, an optional base argument was added to math.log() to make it easier to compute logarithms for bases other than e and 10. (Contributed by Raymond Hettinger.)

  • Several new POSIX functions (getpgid(), killpg(), lchown(), loadavg(), major(), makedev(), minor(), and mknod()) were added to the posix module that underlies the os module. (Contributed by Gustavo Niemeyer, Geert Jansen, and Denis S. Otkidach.)

  • In the os module, the *stat() family of functions can now report fractions of a second in a timestamp. Such time stamps are represented as floats, similar to the value returned by time.time().

    During testing, it was found that some applications will break if time stamps are floats. For compatibility, when using the tuple interface of the stat_result time stamps will be represented as integers. When using named fields (a feature first introduced in Python 2.2), time stamps are still represented as integers, unless os.stat_float_times() is invoked to enable float return values:

    >>> os.stat("/tmp").st_mtime
    1034791200
    >>> os.stat_float_times(True)
    >>> os.stat("/tmp").st_mtime
    1034791200.6335014
    

    In Python 2.4, the default will change to always returning floats.

    Application developers should enable this feature only if all their libraries work properly when confronted with floating point time stamps, or if they use the tuple API. If used, the feature should be activated on an application level instead of trying to enable it on a per-use basis.

  • The optparse module contains a new parser for command-line arguments that can convert option values to a particular Python type and will automatically generate a usage message. See the following section for more details.

  • The old and never-documented linuxaudiodev module has been deprecated, and a new version named ossaudiodev has been added. The module was renamed because the OSS sound drivers can be used on platforms other than Linux, and the interface has also been tidied and brought up to date in various ways. (Contributed by Greg Ward and Nicholas FitzRoy-Dale.)

  • The new platform module contains a number of functions that try to determine various properties of the platform you’re running on. There are functions for getting the architecture, CPU type, the Windows OS version, and even the Linux distribution version. (Contributed by Marc-André Lemburg.)

  • The parser objects provided by the pyexpat module can now optionally buffer character data, resulting in fewer calls to your character data handler and therefore faster performance. Setting the parser object’s buffer_text attribute to True will enable buffering.

  • The sample(population, k) function was added to the random module. population is a sequence or xrange object containing the elements of a population, and sample() chooses k elements from the population without replacing chosen elements. k can be any value up to len(population). For example:

    >>> days = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'St', 'Sn']
    >>> random.sample(days, 3)      # Choose 3 elements
    ['St', 'Sn', 'Th']
    >>> random.sample(days, 7)      # Choose 7 elements
    ['Tu', 'Th', 'Mo', 'We', 'St', 'Fr', 'Sn']
    >>> random.sample(days, 7)      # Choose 7 again
    ['We', 'Mo', 'Sn', 'Fr', 'Tu', 'St', 'Th']
    >>> random.sample(days, 8)      # Can't choose eight
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
      File "random.py", line 414, in sample
          raise ValueError, "sample larger than population"
    ValueError: sample larger than population
    >>> random.sample(xrange(1,10000,2), 10)   # Choose ten odd nos. under 10000
    [3407, 3805, 1505, 7023, 2401, 2267, 9733, 3151, 8083, 9195]
    

    The random module now uses a new algorithm, the Mersenne Twister, implemented in C. It’s faster and more extensively studied than the previous algorithm.

    (All changes contributed by Raymond Hettinger.)

  • The readline module also gained a number of new functions: get_history_item(), get_current_history_length(), and redisplay().

  • The rexec and Bastion modules have been declared dead, and attempts to import them will fail with a RuntimeError. New-style classes provide new ways to break out of the restricted execution environment provided by rexec, and no one has interest in fixing them or time to do so. If you have applications using rexec, rewrite them to use something else.

    (Sticking with Python 2.2 or 2.1 will not make your applications any safer because there are known bugs in the rexec module in those versions. To repeat: if you’re using rexec, stop using it immediately.)

  • The rotor module has been deprecated because the algorithm it uses for encryption is not believed to be secure. If you need encryption, use one of the several AES Python modules that are available separately.

  • The shutil module gained a move(src, dest) function that recursively moves a file or directory to a new location.

  • Support for more advanced POSIX signal handling was added to the signal but then removed again as it proved impossible to make it work reliably across platforms.

  • The socket module now supports timeouts. You can call the settimeout(t) method on a socket object to set a timeout of t seconds. Subsequent socket operations that take longer than t seconds to complete will abort and raise a socket.timeout exception.

    The original timeout implementation was by Tim O’Malley. Michael Gilfix integrated it into the Python socket module and shepherded it through a lengthy review. After the code was checked in, Guido van Rossum rewrote parts of it. (This is a good example of a collaborative development process in action.)

  • On Windows, the socket module now ships with Secure Sockets Layer (SSL) support.

  • The value of the C PYTHON_API_VERSION macro is now exposed at the Python level as sys.api_version. The current exception can be cleared by calling the new sys.exc_clear() function.

  • The new tarfile module allows reading from and writing to tar-format archive files. (Contributed by Lars Gustäbel.)

  • The new textwrap module contains functions for wrapping strings containing paragraphs of text. The wrap(text, width) function takes a string and returns a list containing the text split into lines of no more than the chosen width. The fill(text, width) function returns a single string, reformatted to fit into lines no longer than the chosen width. (As you can guess, fill() is built on top of wrap(). For example:

    >>> import textwrap
    >>> paragraph = "Not a whit, we defy augury: ... more text ..."
    >>> textwrap.wrap(paragraph, 60)
    ["Not a whit, we defy augury: there's a special providence in",
     "the fall of a sparrow. If it be now, 'tis not to come; if it",
     ...]
    >>> print textwrap.fill(paragraph, 35)
    Not a whit, we defy augury: there's
    a special providence in the fall of
    a sparrow. If it be now, 'tis not
    to come; if it be not to come, it
    will be now; if it be not now, yet
    it will come: the readiness is all.
    >>>
    

    The module also contains a TextWrapper class that actually implements the text wrapping strategy. Both the TextWrapper class and the wrap() and fill() functions support a number of additional keyword arguments for fine-tuning the formatting; consult the module’s documentation for details. (Contributed by Greg Ward.)

  • The thread and threading modules now have companion modules, dummy_thread and dummy_threading, that provide a do-nothing implementation of the thread module’s interface for platforms where threads are not supported. The intention is to simplify thread-aware modules (ones that don’t rely on threads to run) by putting the following code at the top:

    try:
        import threading as _threading
    except ImportError:
        import dummy_threading as _threading
    

    In this example, _threading is used as the module name to make it clear that the module being used is not necessarily the actual threading module. Code can call functions and use classes in _threading whether or not threads are supported, avoiding an if statement and making the code slightly clearer. This module will not magically make multithreaded code run without threads; code that waits for another thread to return or to do something will simply hang forever.

  • The time module’s strptime() function has long been an annoyance because it uses the platform C library’s strptime() implementation, and different platforms sometimes have odd bugs. Brett Cannon contributed a portable implementation that’s written in pure Python and should behave identically on all platforms.

  • The new timeit module helps measure how long snippets of Python code take to execute. The timeit.py file can be run directly from the command line, or the module’s Timer class can be imported and used directly. Here’s a short example that figures out whether it’s faster to convert an 8-bit string to Unicode by appending an empty Unicode string to it or by using the unicode() function:

    import timeit
    
    timer1 = timeit.Timer('unicode("abc")')
    timer2 = timeit.Timer('"abc" + u""')
    
    # Run three trials
    print timer1.repeat(repeat=3, number=100000)
    print timer2.repeat(repeat=3, number=100000)
    
    # On my laptop this outputs:
    # [0.36831796169281006, 0.37441694736480713, 0.35304892063140869]
    # [0.17574405670166016, 0.18193507194519043, 0.17565798759460449]
    
  • The Tix module has received various bug fixes and updates for the current version of the Tix package.

  • The Tkinter module now works with a thread-enabled version of Tcl. Tcl’s threading model requires that widgets only be accessed from the thread in which they’re created; accesses from another thread can cause Tcl to panic. For certain Tcl interfaces, Tkinter will now automatically avoid this when a widget is accessed from a different thread by marshalling a command, passing it to the correct thread, and waiting for the results. Other interfaces can’t be handled automatically but Tkinter will now raise an exception on such an access so that you can at least find out about the problem. See https://mail.python.org/pipermail/python-dev/2002-December/031107.html for a more detailed explanation of this change. (Implemented by Martin von Löwis.)

  • Calling Tcl methods through _tkinter no longer returns only strings. Instead, if Tcl returns other objects those objects are converted to their Python equivalent, if one exists, or wrapped with a _tkinter.Tcl_Obj object if no Python equivalent exists. This behavior can be controlled through the wantobjects() method of tkapp objects.

    When using _tkinter through the Tkinter module (as most Tkinter applications will), this feature is always activated. It should not cause compatibility problems, since Tkinter would always convert string results to Python types where possible.

    If any incompatibilities are found, the old behavior can be restored by setting the wantobjects variable in the Tkinter module to false before creating the first tkapp object.

    import Tkinter
    Tkinter.wantobjects = 0
    

    Any breakage caused by this change should be reported as a bug.

  • The UserDict module has a new DictMixin class which defines all dictionary methods for classes that already have a minimum mapping interface. This greatly simplifies writing classes that need to be substitutable for dictionaries, such as the classes in the shelve module.

    Adding the mix-in as a superclass provides the full dictionary interface whenever the class defines __getitem__(), __setitem__(), __delitem__(), and keys(). For example:

    >>> import UserDict
    >>> class SeqDict(UserDict.DictMixin):
    ...     """Dictionary lookalike implemented with lists."""
    ...     def __init__(self):
    ...         self.keylist = []
    ...         self.valuelist = []
    ...     def __getitem__(self, key):
    ...         try:
    ...             i = self.keylist.index(key)
    ...         except ValueError:
    ...             raise KeyError
    ...         return self.valuelist[i]
    ...     def __setitem__(self, key, value):
    ...         try:
    ...             i = self.keylist.index(key)
    ...             self.valuelist[i] = value
    ...         except ValueError:
    ...             self.keylist.append(key)
    ...             self.valuelist.append(value)
    ...     def __delitem__(self, key):
    ...         try:
    ...             i = self.keylist.index(key)
    ...         except ValueError:
    ...             raise KeyError
    ...         self.keylist.pop(i)
    ...         self.valuelist.pop(i)
    ...     def keys(self):
    ...         return list(self.keylist)
    ...
    >>> s = SeqDict()
    >>> dir(s)      # See that other dictionary methods are implemented
    ['__cmp__', '__contains__', '__delitem__', '__doc__', '__getitem__',
     '__init__', '__iter__', '__len__', '__module__', '__repr__',
     '__setitem__', 'clear', 'get', 'has_key', 'items', 'iteritems',
     'iterkeys', 'itervalues', 'keylist', 'keys', 'pop', 'popitem',
     'setdefault', 'update', 'valuelist', 'values']
    

    (Contributed by Raymond Hettinger.)

  • The DOM implementation in xml.dom.minidom can now generate XML output in a particular encoding by providing an optional encoding argument to the toxml() and toprettyxml() methods of DOM nodes.

  • The xmlrpclib module now supports an XML-RPC extension for handling nil data values such as Python’s None. Nil values are always supported on unmarshalling an XML-RPC response. To generate requests containing None, you must supply a true value for the allow_none parameter when creating a Marshaller instance.

  • The new DocXMLRPCServer module allows writing self-documenting XML-RPC servers. Run it in demo mode (as a program) to see it in action. Pointing the Web browser to the RPC server produces pydoc-style documentation; pointing xmlrpclib to the server allows invoking the actual methods. (Contributed by Brian Quinlan.)

  • Support for internationalized domain names (RFCs 3454, 3490, 3491, and 3492) has been added. The «idna» encoding can be used to convert between a Unicode domain name and the ASCII-compatible encoding (ACE) of that name.

    >{}>{}> u"www.Alliancefrançaise.nu".encode("idna")
    'www.xn--alliancefranaise-npb.nu'
    

    The socket module has also been extended to transparently convert Unicode hostnames to the ACE version before passing them to the C library. Modules that deal with hostnames such as httplib and ftplib) also support Unicode host names; httplib also sends HTTP Host headers using the ACE version of the domain name. urllib supports Unicode URLs with non-ASCII host names as long as the path part of the URL is ASCII only.

    To implement this change, the stringprep module, the mkstringprep tool and the punycode encoding have been added.

Date/Time Type

Date and time types suitable for expressing timestamps were added as the datetime module. The types don’t support different calendars or many fancy features, and just stick to the basics of representing time.

The three primary types are: date, representing a day, month, and year; time, consisting of hour, minute, and second; and datetime, which contains all the attributes of both date and time. There’s also a timedelta class representing differences between two points in time, and time zone logic is implemented by classes inheriting from the abstract tzinfo class.

You can create instances of date and time by either supplying keyword arguments to the appropriate constructor, e.g. datetime.date(year=1972, month=10, day=15), or by using one of a number of class methods. For example, the date.today() class method returns the current local date.

Once created, instances of the date/time classes are all immutable. There are a number of methods for producing formatted strings from objects:

>>> import datetime
>>> now = datetime.datetime.now()
>>> now.isoformat()
'2002-12-30T21:27:03.994956'
>>> now.ctime()  # Only available on date, datetime
'Mon Dec 30 21:27:03 2002'
>>> now.strftime('%Y %d %b')
'2002 30 Dec'

The replace() method allows modifying one or more fields of a date or datetime instance, returning a new instance:

>>> d = datetime.datetime.now()
>>> d
datetime.datetime(2002, 12, 30, 22, 15, 38, 827738)
>>> d.replace(year=2001, hour = 12)
datetime.datetime(2001, 12, 30, 12, 15, 38, 827738)
>>>

Instances can be compared, hashed, and converted to strings (the result is the same as that of isoformat()). date and datetime instances can be subtracted from each other, and added to timedelta instances. The largest missing feature is that there’s no standard library support for parsing strings and getting back a date or datetime.

For more information, refer to the module’s reference documentation. (Contributed by Tim Peters.)

The optparse Module

The getopt module provides simple parsing of command-line arguments. The new optparse module (originally named Optik) provides more elaborate command-line parsing that follows the Unix conventions, automatically creates the output for --help, and can perform different actions for different options.

You start by creating an instance of OptionParser and telling it what your program’s options are.

import sys
from optparse import OptionParser

op = OptionParser()
op.add_option('-i', '--input',
              action='store', type='string', dest='input',
              help='set input filename')
op.add_option('-l', '--length',
              action='store', type='int', dest='length',
              help='set maximum length of output')

Parsing a command line is then done by calling the parse_args() method.

options, args = op.parse_args(sys.argv[1:])
print options
print args

This returns an object containing all of the option values, and a list of strings containing the remaining arguments.

Invoking the script with the various arguments now works as you’d expect it to. Note that the length argument is automatically converted to an integer.

$ ./python opt.py -i data arg1
<Values at 0x400cad4c: {'input': 'data', 'length': None}>
['arg1']
$ ./python opt.py --input=data --length=4
<Values at 0x400cad2c: {'input': 'data', 'length': 4}>
[]
$

The help message is automatically generated for you:

$ ./python opt.py --help
usage: opt.py [options]

options:
  -h, --help            show this help message and exit
  -iINPUT, --input=INPUT
                        set input filename
  -lLENGTH, --length=LENGTH
                        set maximum length of output
$

See the module’s documentation for more details.

Optik was written by Greg Ward, with suggestions from the readers of the Getopt SIG.

Pymalloc: A Specialized Object Allocator

Pymalloc, a specialized object allocator written by Vladimir Marangozov, was a feature added to Python 2.1. Pymalloc is intended to be faster than the system malloc() and to have less memory overhead for allocation patterns typical of Python programs. The allocator uses C’s malloc() function to get large pools of memory and then fulfills smaller memory requests from these pools.

In 2.1 and 2.2, pymalloc was an experimental feature and wasn’t enabled by default; you had to explicitly enable it when compiling Python by providing the --with-pymalloc option to the configure script. In 2.3, pymalloc has had further enhancements and is now enabled by default; you’ll have to supply --without-pymalloc to disable it.

This change is transparent to code written in Python; however, pymalloc may expose bugs in C extensions. Authors of C extension modules should test their code with pymalloc enabled, because some incorrect code may cause core dumps at runtime.

There’s one particularly common error that causes problems. There are a number of memory allocation functions in Python’s C API that have previously just been aliases for the C library’s malloc() and free(), meaning that if you accidentally called mismatched functions the error wouldn’t be noticeable. When the object allocator is enabled, these functions aren’t aliases of malloc() and free() any more, and calling the wrong function to free memory may get you a core dump. For example, if memory was allocated using PyObject_Malloc(), it has to be freed using PyObject_Free(), not free(). A few modules included with Python fell afoul of this and had to be fixed; doubtless there are more third-party modules that will have the same problem.

As part of this change, the confusing multiple interfaces for allocating memory have been consolidated down into two API families. Memory allocated with one family must not be manipulated with functions from the other family. There is one family for allocating chunks of memory and another family of functions specifically for allocating Python objects.

Thanks to lots of work by Tim Peters, pymalloc in 2.3 also provides debugging features to catch memory overwrites and doubled frees in both extension modules and in the interpreter itself. To enable this support, compile a debugging version of the Python interpreter by running configure with --with-pydebug.

To aid extension writers, a header file Misc/pymemcompat.h is distributed with the source to Python 2.3 that allows Python extensions to use the 2.3 interfaces to memory allocation while compiling against any version of Python since 1.5.2. You would copy the file from Python’s source distribution and bundle it with the source of your extension.

Ver también

https://hg.python.org/cpython/file/default/Objects/obmalloc.c

For the full details of the pymalloc implementation, see the comments at the top of the file Objects/obmalloc.c in the Python source code. The above link points to the file within the python.org SVN browser.

Build and C API Changes

Changes to Python’s build process and to the C API include:

  • The cycle detection implementation used by the garbage collection has proven to be stable, so it’s now been made mandatory. You can no longer compile Python without it, and the --with-cycle-gc switch to configure has been removed.

  • Python can now optionally be built as a shared library (libpython2.3.so) by supplying --enable-shared when running Python’s configure script. (Contributed by Ondrej Palkovsky.)

  • The DL_EXPORT and DL_IMPORT macros are now deprecated. Initialization functions for Python extension modules should now be declared using the new macro PyMODINIT_FUNC, while the Python core will generally use the PyAPI_FUNC and PyAPI_DATA macros.

  • The interpreter can be compiled without any docstrings for the built-in functions and modules by supplying --without-doc-strings to the configure script. This makes the Python executable about 10% smaller, but will also mean that you can’t get help for Python’s built-ins. (Contributed by Gustavo Niemeyer.)

  • The PyArg_NoArgs() macro is now deprecated, and code that uses it should be changed. For Python 2.2 and later, the method definition table can specify the METH_NOARGS flag, signalling that there are no arguments, and the argument checking can then be removed. If compatibility with pre-2.2 versions of Python is important, the code could use PyArg_ParseTuple(args, "") instead, but this will be slower than using METH_NOARGS.

  • PyArg_ParseTuple() accepts new format characters for various sizes of unsigned integers: B for unsigned char, H for unsigned short int, I for unsigned int, and K for unsigned long long.

  • A new function, PyObject_DelItemString(mapping, char *key) was added as shorthand for PyObject_DelItem(mapping, PyString_New(key)).

  • File objects now manage their internal string buffer differently, increasing it exponentially when needed. This results in the benchmark tests in Lib/test/test_bufio.py speeding up considerably (from 57 seconds to 1.7 seconds, according to one measurement).

  • It’s now possible to define class and static methods for a C extension type by setting either the METH_CLASS or METH_STATIC flags in a method’s PyMethodDef structure.

  • Python now includes a copy of the Expat XML parser’s source code, removing any dependence on a system version or local installation of Expat.

  • If you dynamically allocate type objects in your extension, you should be aware of a change in the rules relating to the __module__ and __name__ attributes. In summary, you will want to ensure the type’s dictionary contains a '__module__' key; making the module name the part of the type name leading up to the final period will no longer have the desired effect. For more detail, read the API reference documentation or the source.

Port-Specific Changes

Support for a port to IBM’s OS/2 using the EMX runtime environment was merged into the main Python source tree. EMX is a POSIX emulation layer over the OS/2 system APIs. The Python port for EMX tries to support all the POSIX-like capability exposed by the EMX runtime, and mostly succeeds; fork() and fcntl() are restricted by the limitations of the underlying emulation layer. The standard OS/2 port, which uses IBM’s Visual Age compiler, also gained support for case-sensitive import semantics as part of the integration of the EMX port into CVS. (Contributed by Andrew MacIntyre.)

On MacOS, most toolbox modules have been weaklinked to improve backward compatibility. This means that modules will no longer fail to load if a single routine is missing on the current OS version. Instead calling the missing routine will raise an exception. (Contributed by Jack Jansen.)

The RPM spec files, found in the Misc/RPM/ directory in the Python source distribution, were updated for 2.3. (Contributed by Sean Reifschneider.)

Other new platforms now supported by Python include AtheOS (http://www.atheos.cx/), GNU/Hurd, and OpenVMS.

Other Changes and Fixes

As usual, there were a bunch of other improvements and bugfixes scattered throughout the source tree. A search through the CVS change logs finds there were 523 patches applied and 514 bugs fixed between Python 2.2 and 2.3. Both figures are likely to be underestimates.

Some of the more notable changes are:

  • If the PYTHONINSPECT environment variable is set, the Python interpreter will enter the interactive prompt after running a Python program, as if Python had been invoked with the -i option. The environment variable can be set before running the Python interpreter, or it can be set by the Python program as part of its execution.

  • The regrtest.py script now provides a way to allow «all resources except foo.» A resource name passed to the -u option can now be prefixed with a hyphen ('-') to mean «remove this resource.» For example, the option “-uall,-bsddb” could be used to enable the use of all resources except bsddb.

  • The tools used to build the documentation now work under Cygwin as well as Unix.

  • The SET_LINENO opcode has been removed. Back in the mists of time, this opcode was needed to produce line numbers in tracebacks and support trace functions (for, e.g., pdb). Since Python 1.5, the line numbers in tracebacks have been computed using a different mechanism that works with «python -O». For Python 2.3 Michael Hudson implemented a similar scheme to determine when to call the trace function, removing the need for SET_LINENO entirely.

    It would be difficult to detect any resulting difference from Python code, apart from a slight speed up when Python is run without -O.

    C extensions that access the f_lineno field of frame objects should instead call PyCode_Addr2Line(f->f_code, f->f_lasti). This will have the added effect of making the code work as desired under «python -O» in earlier versions of Python.

    A nifty new feature is that trace functions can now assign to the f_lineno attribute of frame objects, changing the line that will be executed next. A jump command has been added to the pdb debugger taking advantage of this new feature. (Implemented by Richie Hindle.)

Porting to Python 2.3

This section lists previously described changes that may require changes to your code:

  • yield is now always a keyword; if it’s used as a variable name in your code, a different name must be chosen.

  • For strings X and Y, X in Y now works if X is more than one character long.

  • The int() type constructor will now return a long integer instead of raising an OverflowError when a string or floating-point number is too large to fit into an integer.

  • If you have Unicode strings that contain 8-bit characters, you must declare the file’s encoding (UTF-8, Latin-1, or whatever) by adding a comment to the top of the file. See section PEP 263: Codificación del código fuente for more information.

  • Calling Tcl methods through _tkinter no longer returns only strings. Instead, if Tcl returns other objects those objects are converted to their Python equivalent, if one exists, or wrapped with a _tkinter.Tcl_Obj object if no Python equivalent exists.

  • Large octal and hex literals such as 0xffffffff now trigger a FutureWarning. Currently they’re stored as 32-bit numbers and result in a negative value, but in Python 2.4 they’ll become positive long integers.

    There are a few ways to fix this warning. If you really need a positive number, just add an L to the end of the literal. If you’re trying to get a 32-bit integer with low bits set and have previously used an expression such as ~(1 << 31), it’s probably clearest to start with all bits set and clear the desired upper bits. For example, to clear just the top bit (bit 31), you could write 0xffffffffL &~(1L<<31).

  • You can no longer disable assertions by assigning to __debug__.

  • The Distutils setup() function has gained various new keyword arguments such as depends. Old versions of the Distutils will abort if passed unknown keywords. A solution is to check for the presence of the new get_distutil_options() function in your setup.py and only uses the new keywords with a version of the Distutils that supports them:

    from distutils import core
    
    kw = {'sources': 'foo.c', ...}
    if hasattr(core, 'get_distutil_options'):
        kw['depends'] = ['foo.h']
    ext = Extension(**kw)
    
  • Using None as a variable name will now result in a SyntaxWarning warning.

  • Names of extension types defined by the modules included with Python now contain the module and a '.' in front of the type name.

Acknowledgements

The author would like to thank the following people for offering suggestions, corrections and assistance with various drafts of this article: Jeff Bauer, Simon Brunning, Brett Cannon, Michael Chermside, Andrew Dalke, Scott David Daniels, Fred L. Drake, Jr., David Fraser, Kelly Gerber, Raymond Hettinger, Michael Hudson, Chris Lambert, Detlef Lannert, Martin von Löwis, Andrew MacIntyre, Lalo Martins, Chad Netzer, Gustavo Niemeyer, Neal Norwitz, Hans Nowak, Chris Reedy, Francesco Ricciardi, Vinay Sajip, Neil Schemenauer, Roman Suzi, Jason Tishler, Just van Rossum.