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 conjunto. La clase Set
es para conjuntos mutables, conjuntos a los que se les pueden agregar y quitar miembros. La clase ImmutableSet
es para conjuntos que no se pueden modificar y, por lo tanto, las instancias de ImmutableSet
se pueden usar como claves de diccionario. Los conjuntos se construyen sobre diccionarios, por lo que los elementos dentro de un conjunto deben ser codificables.
Aquí hay un ejemplo simple:
>>> importar conjuntos
>>> S = conjuntos.Set([1,2,3])
>>> S
Set([1, 2, 3])
>>> 1 en S
Verdadero
>>> 0 en S
Falso
>>> S.add(5)
>>> S.remove(3)
>>> S
Set([1, 2, 5])
>>>
La unión e intersección de conjuntos se puede calcular con los métodos union()
y intersection()
; una notación alternativa utiliza los operadores bit a bit &
y |
. Los conjuntos mutables también tienen versiones de estos métodos, union_update()
y intersection_update()
.
>>> S1 = conjuntos.Set([1,2,3])
>>> S2 = conjuntos.Set([4,5,6])
>>> S1.union(S2)
Set([1, 2, 3, 4, 5, 6])
>>> S1 | S2 # Notación alternativa
Set([1, 2, 3, 4, 5, 6])
>>> S1.intersection(S2)
Set([])
>>> S1 y S2 # Notación alternativa
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 en 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. Nuevamente, existe una notación alternativa (^
) y una versión en el lugar con el extraño nombre symmetric_difference_update()
.
>>> S1 = conjuntos.Conjunto([1,2,3,4])
>>> S2 = conjuntos.Conjunto([3,4,5,6])
>>> S1.diferencia_simétrica(S2)
Conjunto([1, 2, 5, 6])
>>> S1 ^ S2
Conjunto([1, 2, 5, 6])
>>>
También existen los métodos issubset()
y issuperset()
para comprobar si un conjunto es un subconjunto o superconjunto de otro:
>>> S1 = conjuntos.Set([1,2,3])
>>> S2 = conjuntos.Set([2,3])
>>> S2.issubset(S1)
Verdadero
>>> S1.issubset(S2)
Falso
>>> S1.issuperset(S2)
Verdadero
>>>
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):
para i en rango(N):
rendimiento 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
<objeto generador en 0x8117f90>
>>> gen.next()
0
>>> gen.next()
1
>>> gen.next()
2
>>> gen.next()
Traceback (última llamada más reciente):
Archivo "stdin", línea 1, en ?
Archivo "stdin", línea 2, en 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
# Un generador recursivo que genera hojas de árboles en orden.
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://www2.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://www2.cs.arizona.edu/icon/docs/ipd266.htm da una idea de cómo es esto:
oración := "Guardarlo en el puerto vecino"
si (i := find("o", oración)) > 5 entonces write(i)
En Icon, la función find()
devuelve los índices en los que se encuentra la subcadena «o»: 3, 23, 33. En la declaración if
, a i
primero se le asigna un valor de 3, pero 3 es menor que 5, por lo que la comparación falla y Icon la vuelve a intentar 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
Archivo: /tmp/example.zip
Longitud Fecha Hora Nombre
-------- ---- ---- ----
8467 11-26-02 22:30 jwzthreading.py
-------- -------
8467 1 archivo
amk@nyman:~/src/python$ ./python
Python 2.3 (#1, 1 de agosto de 2003, 19:54:32)
>>> import sys
>>> sys.path.insert(0, '/tmp/example.zip') # Agregar archivo .zip al principio de la ruta
>>> import jwzthreading
>>> jwzthreading.__file__
'/tmp/ejemplo.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 ahora permite el uso de cadenas Unicode arbitrarias (dentro de las limitaciones del sistema de archivos) para todas las funciones que esperan nombres de archivos, en particular la función incorporada open()
. Si se pasa una cadena Unicode a os.listdir()
, Python ahora devuelve una lista de cadenas Unicode. Una nueva función, os.getcwdu()
, devuelve 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 ahora pueden admitir convenciones de fin de línea distintas a 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 leer en modo universal newlines. Las tres convenciones de fin de línea se traducirán a '\n'
en las cadenas devueltas por los distintos métodos de archivo, como read()
y readline()
.
También se utiliza la compatibilidad universal con saltos de línea al importar módulos y al ejecutar un archivo con la función execfile()
. Esto significa que los módulos de Python se pueden compartir 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:
para i en rango(len(L)):
item = L[i]
# ... calcular algún resultado basado en el elemento ...
L[i] = resultado
Esto se puede reescribir usando enumerate()
como:
para i, elemento en enumerate(L):
# ... calcular algún resultado basado en el elemento ...
L[i] = resultado
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 se ocupará de uno o más objetos Logger
, cada uno de ellos 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, puede tener instancias Logger
denominadas server
, server.auth
y server.network
. Las dos últimas instancias están por debajo de server
en la jerarquía. Esto significa que si aumenta el nivel de detalle de server
o dirige los mensajes server
a un controlador diferente, los cambios también se aplicarán a los registros registrados en server.auth
y server.network
. También hay un Logger
raíz que es el padre de todos los demás registradores.
Para usos sencillos, el paquete logging
contiene algunas funciones de conveniencia que siempre utilizan la raíz log:
import logging
logging.debug('Información de depuración')
logging.info('Mensaje informativo')
logging.warning('Advertencia: no se encontró el archivo de configuración %s', 'server.conf')
logging.error('Se produjo un error')
logging.critical('Error crítico: apagando el sistema')
Esto produce la siguiente salida:
ADVERTENCIA:root:Advertencia:no se encontró el archivo de configuración server.conf
ERROR:root:Se produjo un error
CRÍTICO:root:Error crítico: se está apagando
En la configuración predeterminada, se suprimen los mensajes informativos y de depuración 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()
en el registrador raíz.
Observe el uso de operadores de formato de cadena en la llamada warning()
; todas las funciones para registrar 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 seguimiento más reciente. Cualquiera de las otras funciones también registrará el seguimiento si especifica un valor verdadero para el argumento de palabra clave exc_info.
def f():
try: 1/0
except: logging.exception('Problema registrado')
f()
Esto produce la siguiente salida:
ERROR:root:Problema registrado
Traceback (última llamada más reciente):
Archivo "t.py", línea 6, en f
1/0
ZeroDivisionError: división entera o módulo por cero
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('servidor')
...
log.info('Escuchando en el puerto %i', puerto)
...
log.critical('Disco lleno')
...
Los registros normalmente se propagan hacia arriba en la jerarquía, por lo que un mensaje registrado en server.auth
también es visto por server
y root
, pero un Logger
puede evitar esto configurando su atributo propagate
en False
.
El paquete logging
proporciona más clases que se pueden personalizar. Cuando se le indica a una instancia Logger
que registre un mensaje, crea una instancia LogRecord
que se envía a cualquier cantidad de instancias Handler
diferentes. Los registradores y controladores también pueden tener una lista adjunta de filtros, y cada filtro puede hacer que se ignore el LogRecord
o puede modificar el registro antes de pasarlo. Cuando finalmente se generan, las instancias LogRecord
se convierten en texto mediante una clase Formatter
. Todas estas clases se pueden reemplazar por sus 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 agregó un tipo booleano a Python 2.3. Se agregaron dos nuevas constantes al módulo __builtin__
, True
y False
. (Las constantes True
y False
se agregaron a las funciones integradas en Python 2.2.1, pero las versiones 2.2.1 simplemente se configuran en valores enteros de 1 y 0 y no son de 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)
Verdadero
>>> bool(0)
Falso
>>> bool([])
Falso
>>> bool( (1,) )
Verdadero
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')
Verdadero
>>> isinstance(obj, lista)
Verdadero
>>> isinstance(obj, tupla)
Falso
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.
>>> Verdadero + 1
2
>>> Falso + 1
1
>>> Falso * 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 que el catálogo sea un poco más útil, se ha añadido un nuevo argumento de palabra clave opcional classifiers a la función setup()
de Distutils. Se puede proporcionar 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¶
Si bien ha sido posible escribir ganchos de importación personalizados desde que se introdujo el módulo ihooks
en Python 1.3, nadie ha estado realmente satisfecho con ello 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 ninguna de ellas ha tenido mucha aceptación y ninguna de ellas se podía usar fácilmente desde el código C.
PEP 302 toma prestadas ideas de sus predecesores, especialmente del módulo iu
de Gordon McMillan. Se han añadido tres elementos nuevos 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ónImportError
si no puede manejar esta ruta.sys.path_importer_cache
almacena en caché los objetos del importador para cada ruta, por lo quesys.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 comprobarsys.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):
para mp en sys.meta_path:
loader = mp(fullname)
si loader no es None:
<module> = loader.load_module(fullname)
para path en sys.path:
para hook en sys.path_hooks:
try:
importer = hook(path)
except ImportError:
# ImportError, así que prueba los otros ganchos de path
pass
de lo contrario:
loader = importer.find_module(fullname)
<module> = loader.load_module(fullname)
# ¡No encontrado!
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:
Costos,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:
"Costos",150,200,3.95,"Incluye impuestos, envío y artículos varios"
Una expresión regular grande y fea puede analizar esto, pero usar el nuevo paquete csv
es mucho más sencillo:
importar csv
entrada = open('archivo_datos', 'rb')
lector = csv.reader(entrada)
para línea en lector:
imprimir línea
La función reader()
acepta varias opciones diferentes. El separador de campo no se limita a la coma y se puede cambiar por cualquier carácter, al igual que los caracteres de comillas y de fin 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 2.3. En 2.2, las clases de nuevo estilo podían ser encurtidas sin dificultad, pero no de forma muy compacta; PEP 307 cita un ejemplo trivial en el que una clase de nuevo estilo da como resultado una cadena encurtida 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 desempaquetado ya no se considera una operación segura. pickle
de la versión 2.2 proporcionaba ganchos para intentar evitar que se desempaquetaran clases no seguras (específicamente, un atributo __safe_for_unpickling__
), pero ninguno de este código fue auditado y, por lo tanto, todo se eliminó en la versión 2.3. No debe desempaquetar datos no confiables en ninguna versión de Python.
Para reducir la sobrecarga de decapado para las clases de estilo nuevo, se agregó una nueva interfaz para personalizar el decapado 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 = rango(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 = rango(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 (última llamada más reciente):
Archivo "<stdin>", línea 1, en ?
ValueError: intento de asignar una secuencia de tamaño 3 a una porción extendida de tamaño 2
La eliminación es más sencilla:
>>> a = rango(4)
>>> a
[0, 1, 2, 3]
>>> a[::2]
[0, 2]
>>> del a[::2]
>>> a
[1, 3]
Ahora también se pueden pasar objetos de corte a los métodos __getitem__()
de las secuencias integradas:
>>> rango(10).__getitem__(sección(0, 5, 2))
[0, 2, 4]
O utilizar los objetos de corte directamente en los subíndices:
>>> rango(10)[segmento(0, 5, 2)]
[0, 2, 4]
Para simplificar la implementación de secuencias que admiten cortes extendidos, los objetos de corte ahora tienen un método indices(length)
que, dada la longitud de una secuencia, devuelve una tupla (start, stop, step)
que se puede pasar directamente a range()
. indices()
maneja los índices omitidos y fuera de límites de una manera consistente con los cortes regulares (¡y esta frase inocua esconde una maraña de detalles confusos!). El método está pensado para usarse de esta manera:
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
yFalse
junto con el tipo incorporadobool
, 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 unOverflowError
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 queisinstance(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 lanzaKeyError
si no lo está:>>> d = {1:2} >>> d {1: 2} >>> d.pop(4) Traceback (última llamada más reciente): Archivo "stdin", línea 1, en ? KeyError: 4 >>> d.pop(1) 2 >>> d.pop(1) Traceback (última llamada más reciente): Archivo "stdin", línea 1, en ? KeyError: 'pop(): el diccionario está vacío' >>> 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 aNone
.(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(rojo=1, azul=2, verde=3, negro=4) {'azul': 2, 'negro': 4, 'verde': 3, 'rojo': 1}
(Contribución de Just van Rossum.)
La expresión
assert
ya no comprueba la banderadebug__
, 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 ahora se pueden llamar, por lo que puede usarlos para crear nuevos objetos, como funciones, clases y módulos. (Esto significa que el módulo
new
puede quedar obsoleto en una versión futura de Python, porque ahora puede usar los objetos de tipo disponibles en el módulotypes
). Por ejemplo, puede crear un nuevo objeto de módulo con el siguiente código:>>> tipos de importación >>> m = tipos.ModuleType('abc','docstring') >>> m <módulo 'abc' (integrado)> >>> 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 utilicewarnings.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 advertenciaSyntaxWarning
. En una futura versión de Python,None
podría convertirse en una palabra clave.El método
xreadlines()
de los objetos de archivo, introducido en Python 2.1, ya no es necesario porque los archivos ahora se comportan 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 puedes escribir simplementefor line in file_obj
. Los objetos de archivo también tienen un nuevo atributoencoding
de solo 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 métodos utilizado por las clases de nuevo estilo ha cambiado, aunque solo 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 usaba una clasificación topológica de los ancestros de una clase, pero 2.3 ahora usa el algoritmo C3 como se describe en el artículo «A Monotonic Superclass Linearization for Dylan». Para entender la motivación de este cambio, lee el artículo The Python 2.3 Method Resolution Order de Michele Simionato, o lee 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 multiproceso alternando entre subprocesos después de ejecutar N bytecodes. El valor predeterminado de N se ha incrementado de 10 a 100 bytecodes, lo que acelera las aplicaciones de un solo subproceso al reducir la sobrecarga de conmutación. Algunas aplicaciones multiproceso pueden sufrir un tiempo de respuesta más lento, pero eso se soluciona fácilmente estableciendo el límite en un número menor utilizando
sys.setcheckinterval(N)
. El límite se puede recuperar con la nueva funciónsys.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 creaba un socket e imprimía su__class__
, obtenía este resultado:>>> s = socket.socket() >>> s.__class__ <tipo 'socket'>
En 2.3, se obtiene esto:
>>> s.__class__ <tipo '_socket.socket'>
Se ha eliminado una de las incompatibilidades observadas entre las clases de estilo antiguo y nuevo: ahora se pueden asignar atributos
__name__
y__bases__
a las clases de estilo nuevo. Existen algunas restricciones sobre lo que se puede asignar a__bases__
similares a 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 evaluabaX 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, yX en Y
retornaráTrue
si X es una subcadena de Y. Si X es una cadena vacía, el resultado es siempreTrue
.>>> 'ab' en 'abcd' Verdadero >>> 'ad' en 'abcd' Falso >>> '' en 'abcd' Verdadero
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()
yrstrip()
ahora tienen un argumento opcional para especificar los caracteres que se eliminarán. El valor predeterminado 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()
yendswith()
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ódulostring
.zfill()
rellena una cadena numérica con ceros a la izquierda hasta que alcanza el ancho especificado. Tenga en cuenta que el operador%
sigue siendo más flexible y potente quezfill()
.>>> '45'.zfill(4) '0045' >>> '12345'.zfill(4) '12345' >>> 'tonto'.zfill(6) '0tonto'
(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 queisinstance(obj, basestring)
devolveráTrue
para cualquier tipo de cadena. Es un tipo completamente abstracto, por lo que no se pueden crear instancias debasestring
.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 objetos de lista ha sido reescrito ampliamente por Tim Peters, y la implementación es significativamente más rápida.La multiplicación de números enteros grandes 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(n2) requerido para el algoritmo de multiplicación de nivel primario. (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 Otros cambios y correcciones para una explicación más larga. (Eliminado por Michael Hudson)Los objetos
xrange()
ahora tienen su propio iterador, lo que hace quefor i in xrange(n)
sea ligeramente más rápido quefor 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 versión anterior del módulo ha cambiado de nombre a
bsddb185
y ya no se compila automáticamente; deberá editarModules/Setup
para habilitarlo. Tenga en cuenta que el nuevo paquetebsddb
está pensado para ser compatible con el módulo anterior, así que asegúrese de informar de los errores si descubre 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 los archivos de su base de datos a la nueva versión. Puede hacerlo con bastante facilidad con los nuevos scriptsdb2pickle.py
ypickle2db.py
que encontrará en el directorioTools/scripts
de la distribución. Si ya ha estado usando el paquete PyBSDDB y lo ha importado comobsddb3
, tendrá que cambiar sus declaracionesimport
para importarlo comobsddb
.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 conzlib
. (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
Extension
de Distutils ahora admite un argumento de constructor adicional llamado depends para enumerar archivos de origen adicionales de los que depende una extensión. Esto permite que Distutils vuelva a compilar el módulo si se modifica alguno de los archivos de dependencia. Por ejemplo, sisampmodule.c
incluye el archivo de encabezadosample.h
, crearía el objetoExtension
de la siguiente manera:ext = Extensión("samp", fuentes=["sampmodule.c"], depende=["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 verifica las variables de entorno
CC
,CFLAGS
,CPP
,LDFLAGS
yCPPFLAGS
, usándolas para anular las configuraciones en la configuración de Python (contribuido por Robert Weber).Anteriormente, el módulo
doctest
solo buscaba casos de prueba en las cadenas de documentación de métodos y funciones públicos, pero ahora también examina los casos de prueba privados. La funciónDocTestSuite()
crea un objetounittest.TestSuite
a partir de un conjunto de pruebasdoctest
.La nueva función
gc.get_referents(object)
retorna una lista de todos los objetos referenciados por object.El módulo
getopt
obtuvo una nueva función,gnu_getopt()
, que admite los mismos argumentos que la funcióngetopt()
existente, pero utiliza el modo de escaneo de estilo GNU. El módulogetopt()
existente deja de procesar opciones tan pronto como se encuentra un argumento que no es una opción, pero en el modo de estilo GNU el procesamiento continúa, lo que significa que se pueden mezclar opciones y argumentos. Por ejemplo:>>> getopt.getopt(['-f', 'nombrearchivo', 'salida', '-v'], 'f:v') ([('-f', 'nombrearchivo')], ['salida', '-v']) >>> getopt.gnu_getopt(['-f', 'nombrearchivo', 'salida', '-v'], 'f:v') ([('-f', 'nombrearchivo'), ('-v', '')], ['salida'])
(Contribución de Peter Åstrand.)
Los módulos
grp
,pwd
yresource
retornan ahora tuplas mejoradas:>>> importar 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 cola de montón. Un montón es una estructura de datos similar a una matriz que mantiene los elementos en un orden parcialmente ordenado de modo que, para cada índice k,heap[k] <= heap[2*k+1]
yheap[k] <= heap[2*k+2]
, se elimina rápidamente el elemento más pequeño y se inserta un elemento nuevo mientras se mantiene la propiedad de montón O(log n). (Consulte https://xlinux.nist.gov/dads//HTML/priorityque.html para obtener más información sobre la estructura de datos de la cola de prioridad).El módulo
heapq
proporciona las funcionesheappush()
yheappop()
para agregar y eliminar elementos mientras se mantiene la propiedad de montón sobre algún otro tipo de secuencia mutable de Python. Aquí hay un ejemplo que utiliza una lista de Python:>>> import heapq >>> montón = [] >>> para el elemento en [3, 7, 5, 11, 1]: ... heapq.heappush(montón, elemento) ... >>> montón [1, 3, 5, 11, 7] >>> heapq.heappop(montón) 1 >>> heapq.heappop(montón) 3 >>> montón [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 paqueteidlelib
.El módulo
imaplib
ahora admite IMAP sobre SSL. (Contribuido por Piers Lauder y Tino Lange.)itertools
contiene varias funciones útiles para usar con iteradores, inspiradas en varias funciones proporcionadas por los lenguajes ML y Haskell. Por ejemplo,itertools.ifilter(predicate, iterator)
devuelve todos los elementos del iterador para los que la funciónpredicate()
devuelveTrue
, yitertools.repeat(obj, N)
devuelveobj
N veces. Hay varias otras funciones en el módulo; consulte la documentación de referencia del paquete para obtener más detalles. (Contribuido por Raymond Hettinger).Dos nuevas funciones en el módulo
math
,degrees(rads)
yradians(degs)
, convierten entre radianes y grados. Otras funciones del módulomath
, comomath.sin()
ymath.cos()
, siempre han requerido valores de entrada medidos en radianes. Además, se agregó un argumento opcional base amath.log()
para facilitar el cálculo de logaritmos para bases distintas dee
y10
. (Contribuido por Raymond Hettinger.)Se agregaron varias funciones POSIX nuevas (
getpgid()
,killpg()
,lchown()
,loadavg()
,major()
,makedev()
,minor()
ymknod()
) al móduloposix
que sirve de base al móduloos
. (Contribución de Gustavo Niemeyer, Geert Jansen y Denis S. Otkidach).En el módulo
os
, la familia de funciones*stat()
ahora puede informar fracciones de segundo en una marca de tiempo. Dichas marcas de tiempo se representan como números flotantes, similares al valor devuelto portime.time()
.Durante las pruebas, se descubrió que algunas aplicaciones fallan si las marcas de tiempo son números de punto flotante. Por cuestiones de compatibilidad, al usar la interfaz de tupla de
stat_result
, las marcas de tiempo se representarán como números enteros. Al usar campos con nombre (una característica introducida por primera vez en Python 2.2), las marcas de tiempo aún se representan como números enteros, a menos que se invoqueos.stat_float_times()
para habilitar los valores de retorno de punto flotante:>>> os.stat("/tmp").st_mtime 1034791200 >>> os.stat_float_times(Verdadero) >>> os.stat("/tmp").st_mtime 1034791200.6335014
En Python 2.4, el valor predeterminado cambiará para devolver siempre flotantes.
Los desarrolladores de aplicaciones deberían habilitar esta función solo si todas sus bibliotecas funcionan correctamente cuando se enfrentan a marcas de tiempo de punto flotante o si utilizan la API de tuplas. Si se utiliza, la función debería activarse a nivel de aplicación en lugar de intentar habilitarla según el uso.
El módulo
optparse
contiene un nuevo analizador para argumentos de línea de comandos que puede convertir valores de opción a un tipo de Python en particular y generará automáticamente un mensaje de uso. Consulte la siguiente sección para obtener más detalles.El antiguo módulo
linuxaudiodev
, que nunca se documentó, ha quedado obsoleto y se ha añadido una nueva versión denominadaossaudiodev
. El módulo ha cambiado de nombre porque los controladores de sonido OSS se pueden utilizar en plataformas distintas a Linux y la interfaz también se ha ordenado y actualizado de varias maneras. (Contribución de Greg Ward y Nicholas FitzRoy-Dale).El nuevo módulo
platform
contiene una serie de funciones que intentan determinar varias propiedades de la plataforma en la que se está ejecutando. Hay funciones para obtener la arquitectura, el tipo de CPU, la versión del sistema operativo Windows e incluso la versión de distribución de Linux. (Contribución de Marc-André Lemburg.)Los objetos del analizador proporcionados por el módulo
pyexpat
ahora pueden almacenar en búfer datos de caracteres de manera opcional, lo que genera menos llamadas al controlador de datos de caracteres y, por lo tanto, un rendimiento más rápido. Si se configura el atributobuffer_text
del objeto del analizador enTrue
, se habilitará el almacenamiento en búfer.Se agregó la función
sample(population, k)
al módulorandom
. population es una secuencia o un objetoxrange
que contiene los elementos de una población ysample()
elige elementos k de la población sin reemplazar los elementos elegidos. k puede ser cualquier valor hastalen(population)
. Por ejemplo:>>> days = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'St', 'Sn'] >>> random.sample(days, 3) # Elige 3 elementos ['St', 'Sn', 'Th'] >>> random.sample(days, 7) # Elige 7 elementos ['Tu', 'Th', 'Mo', 'We', 'St', 'Fr', 'Sn'] >>> random.sample(days, 7) # Elige 7 nuevamente ['We', 'Mo', 'Sn', 'Fr', 'Tu', 'St', 'Th'] >>> random.sample(days, 8) # No se pueden elegir ocho Traceback (última llamada más reciente): Archivo "<stdin>", línea 1, en ? Archivo "random.py", línea 414, en ejemplo genera ValueError, "muestra mayor que la población" ValueError: muestra mayor que la población >>> random.sample(xrange(1,10000,2), 10) # Elige diez números impares menores a 10000 [3407, 3805, 1505, 7023, 2401, 2267, 9733, 3151, 8083, 9195]
El módulo
random
ahora usa un nuevo algoritmo, el Mersenne Twister, implementado en C. Es más rápido y más estudiado que el algoritmo anterior.(Parches aportados por Raymond Hettinger)
El módulo
readline
también obtuvo una serie de nuevas funciones:get_history_item()
,get_current_history_length()
yredisplay()
.Los módulos
rexec
yBastion
se han declarado inactivos y los intentos de importarlos fallarán con unRuntimeError
. Las clases de nuevo estilo proporcionan nuevas formas de salir del entorno de ejecución restringido que ofrecerexec
y nadie tiene interés en arreglarlas ni tiempo para hacerlo. Si tiene aplicaciones que utilizanrexec
, reescríbalas para utilizar algo diferente.(Seguir usando Python 2.2 o 2.1 no hará que sus aplicaciones sean más seguras porque hay errores conocidos en el módulo
rexec
en esas versiones. Para repetir: si está usandorexec
, deje de usarlo inmediatamente).El módulo
rotor
ha quedado obsoleto porque se cree que el algoritmo que utiliza para el cifrado no es seguro. Si necesita cifrado, utilice uno de los diversos módulos AES de Python que están disponibles por separado.El módulo
shutil
obtuvo una funciónmove(src, dest)
que mueve recursivamente un archivo o directorio a una nueva ubicación.Se agregó soporte para un manejo de señal POSIX más avanzado al
signal
, pero luego se eliminó nuevamente, ya que resultó imposible hacerlo funcionar de manera confiable en todas las plataformas.El módulo
socket
ahora admite tiempos de espera. Puede llamar al métodosettimeout(t)
en un objeto de socket para establecer un tiempo de espera de t seconds. Subsequent socket operations that take longer than t segundos para completar, abortará y lanzará una excepciónsocket.timeout
.La implementación del tiempo de espera original fue realizada por Tim O’Malley. Michael Gilfix lo integró en el módulo Python
socket
y lo guió a través de una extensa revisión. Después de que se registró el código, Guido van Rossum reescribió partes del mismo. (Este es un buen ejemplo de un proceso de desarrollo colaborativo en acción).En Windows, el módulo
socket
ahora se envía con compatibilidad con Secure Sockets Layer (SSL).El valor de la macro C
PYTHON_API_VERSION
ahora se expone en el nivel de Python comosys.api_version
. La excepción actual se puede eliminar llamando a la nueva funciónsys.exc_clear()
.El nuevo módulo
tarfile
permite leer y escribir en: programa: tar -format archivos de almacenamiento. (Contribución de Lars Gustäbel.)El nuevo módulo
textwrap
contiene funciones para encapsular cadenas que contienen párrafos de texto. La funciónwrap(text, width)
toma una cadena y devuelve una lista que contiene el texto dividido en líneas de un ancho no mayor que el elegido. La funciónfill(text, width)
devuelve una sola cadena, reformateada para que quepa en líneas de un ancho no mayor que el elegido. (Como puede adivinar,fill()
está construido sobrewrap()
. Por ejemplo:>>> import textwrap >>> párrafo = "Ni un ápice, desafiamos el augurio: ... más texto ..." >>> textwrap.wrap(párrafo, 60) ["Ni un ápice, desafiamos el augurio: hay una providencia especial en", "la caída de un gorrión. Si es ahora, no está por venir; si", ...] >>> print textwrap.fill(párrafo, 35) Ni un ápice, desafiamos el augurio: hay una providencia especial en la caída de un gorrión. Si es ahora, no está por venir; si no está por venir, será ahora; si no es ahora, aún vendrá: la preparación lo es todo. >>>
El módulo también contiene una clase
TextWrapper
que implementa la estrategia de ajuste de texto. Tanto la claseTextWrapper
como las funcioneswrap()
yfill()
admiten una serie de argumentos de palabras clave adicionales para ajustar el formato; consulte la documentación del módulo para obtener más detalles. (Contribuido por Greg Ward).Los módulos
thread
ythreading
ahora tienen módulos complementarios,dummy_thread
ydummy_threading
, que proporcionan una implementación sin hacer nada de la interfaz del módulothread
para plataformas donde no se admiten subprocesos. La intención es simplificar los módulos que admiten subprocesos (aquellos que dependen de subprocesos para ejecutarse) colocando el siguiente código en la parte superior:Intente: importar subprocesos como _threading excepto ImportError: importar dummy_threading como _threading
En este ejemplo, se utiliza
_threading
como nombre del módulo para dejar claro que el módulo que se utiliza no es necesariamente el módulothreading
real. El código puede llamar a funciones y usar clases en_threading
independientemente de si se admiten subprocesos o no, lo que evita una declaraciónif
y hace que el código sea un poco más claro. Este módulo no hará que el código multiproceso se ejecute mágicamente sin subprocesos; el código que espera a que otro subproceso regrese o haga algo simplemente se bloqueará para siempre.La función
strptime()
del módulotime
ha sido una molestia durante mucho tiempo porque utiliza la implementaciónstrptime()
de la biblioteca de la plataforma C, y a veces las diferentes plataformas tienen errores extraños. Brett Cannon contribuyó con una implementación portátil que está escrita en Python puro y debería comportarse de manera idéntica en todas las plataformas.El nuevo módulo
timeit
ayuda a medir cuánto tardan en ejecutarse fragmentos de código Python. El archivotimeit.py
se puede ejecutar directamente desde la línea de comandos, o se puede importar y utilizar directamente la claseTimer
del módulo. A continuación, se incluye un breve ejemplo que determina si es más rápido convertir una cadena de 8 bits a Unicode añadiéndole una cadena Unicode vacía o utilizando la funciónunicode()
:import timeit timer1 = timeit.Timer('unicode("abc")') timer2 = timeit.Timer('"abc" + u""') # Ejecutar tres pruebas print timer1.repeat(repeat=3, number=100000) print timer2.repeat(repeat=3, number=100000) # En mi computadora portátil, esto genera: # [0.36831796169281006, 0.37441694736480713, 0.35304892063140869] # [0.17574405670166016, 0.18193507194519043, 0.17565798759460449]
El módulo
Tix
ha recibido varias correcciones de errores y actualizaciones para la versión actual del paquete Tix.El módulo
Tkinter
ahora funciona con una versión de Tcl habilitada para subprocesos. El modelo de subprocesos de Tcl requiere que solo se acceda a los widgets desde el subproceso en el que se crearon; los accesos desde otro subproceso pueden hacer que Tcl entre en pánico. Para ciertas interfaces de Tcl,Tkinter
ahora evitará esto automáticamente cuando se acceda a un widget desde un subproceso diferente mediante la ordenación de un comando, pasándolo al subproceso correcto y esperando los resultados. Otras interfaces no se pueden manejar automáticamente, peroTkinter
ahora generará una excepción en dicho acceso para que al menos pueda averiguar sobre el problema. Consulte https://mail.python.org/pipermail/python-dev/2002-December/031107.html para obtener una explicación más detallada de este cambio. (Implementado por Martin von Löwis).La llamada a métodos Tcl a través de
_tkinter
ya no devuelve solo cadenas. En cambio, si Tcl devuelve otros objetos, esos objetos se convierten en su equivalente de Python, si existe uno, o se encapsulan con un objeto_tkinter.Tcl_Obj
si no existe un equivalente de Python. Este comportamiento se puede controlar a través del métodowantobjects()
de los objetostkapp
.Al utilizar
_tkinter
a través del móduloTkinter
(como lo hacen la mayoría de las aplicaciones de Tkinter), esta función siempre está activada. No debería causar problemas de compatibilidad, ya que Tkinter siempre convertiría los resultados de cadenas a tipos de Python cuando fuera posible.Si se encuentran incompatibilidades, se puede restaurar el comportamiento anterior configurando la variable
wantobjects
en el móduloTkinter
como falsa antes de crear el primer objetotkapp
.importar Tkinter Tkinter.wantobjects = 0
Cualquier rotura causada por este cambio debe notificarse como un error.
El módulo
UserDict
tiene una nueva claseDictMixin
que define todos los métodos de diccionario para las clases que ya tienen una interfaz de mapeo mínima. Esto simplifica enormemente la escritura de clases que deben ser sustituibles por diccionarios, como las clases del móduloshelve
.Al agregar la combinación como superclase, se obtiene la interfaz de diccionario completa siempre que la clase defina
__getitem__()
,__setitem__()
,__delitem__()
ykeys()
. Por ejemplo:>>> import UserDict >>> class SeqDict(UserDict.DictMixin): ... """Similar a un diccionario implementado con listas.""" ... 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) # Verificar que se implementen otros métodos de diccionario ['__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', 'valores']
(Parches aportados por Raymond Hettinger)
La implementación de DOM en
xml.dom.minidom
ahora puede generar salida XML en una codificación particular al proporcionar un argumento de codificación opcional a los métodostoxml()
ytoprettyxml()
de los nodos DOM.El módulo
xmlrpclib
ahora admite una extensión XML-RPC para manejar valores de datos nulos, comoNone
de Python. Los valores nulos siempre se admiten al desagrupar una respuesta XML-RPC. Para generar solicitudes que contenganNone
, debe proporcionar un valor verdadero para el parámetro allow_none al crear una instanciaMarshaller
.El nuevo módulo
DocXMLRPCServer
permite escribir servidores XML-RPC autodocumentados. Ejecútelo en modo de demostración (como programa) para verlo en acción. Al apuntar el navegador web al servidor RPC se genera documentación de estilo pydoc; al apuntar xmlrpclib al servidor se pueden invocar los métodos reales. (Contribuido por Brian Quinlan.)Se ha agregado soporte para nombres de dominio internacionalizados (RFCs 3454, 3490, 3491 y 3492). La codificación «idna» se puede utilizar para convertir entre un nombre de dominio Unicode y la codificación compatible con ASCII (ACE) de ese nombre.
>{}>{}> u"www.Alliancefrançaise.nu".encode("idna") 'www.xn--alliancefranaise-npb.nu'
El módulo
socket
también se ha ampliado para convertir de forma transparente los nombres de host Unicode a la versión ACE antes de pasarlos a la biblioteca C. Los módulos que se ocupan de los nombres de host, comohttplib
yftplib
, también admiten nombres de host Unicode;httplib
también envía encabezados HTTPHost
utilizando la versión ACE del nombre de dominio.urllib
admite URL Unicode con nombres de host que no sean ASCII siempre que la partepath
de la URL sea solo ASCII.Para implementar este cambio, se han agregado el módulo
stringprep
, la herramientamkstringprep
y la codificaciónpunycode
.
Tipo de fecha / hora¶
Se agregaron tipos de fecha y hora adecuados para expresar marcas de tiempo como módulo datetime
. Los tipos no admiten diferentes calendarios ni muchas funciones sofisticadas, y solo se ciñen a los conceptos básicos de la representación del tiempo.
Los tres tipos principales son: date
, que representa un día, un mes y un año; time
, que consta de horas, minutos y segundos; y datetime
, que contiene todos los atributos de date
y time
. También existe una clase timedelta
que representa las diferencias entre dos puntos en el tiempo, y la lógica de la zona horaria se implementa mediante clases que heredan de la clase abstracta tzinfo
.
Puede crear instancias de date
y time
proporcionando argumentos de palabras clave al constructor adecuado, por ejemplo, datetime.date(year=1972, month=10, day=15)
, o utilizando uno de los diversos métodos de clase. Por ejemplo, el método de clase today()
devuelve la fecha local actual.
Una vez creadas, las instancias de las clases de fecha / hora son inmutables. Hay varios métodos para producir cadenas formateadas a partir de objetos:
>>> import datetime
>>> now = datetime.datetime.now()
>>> now.isoformat()
'2002-12-30T21:27:03.994956'
>>> now.ctime() # Solo disponible en fecha, datetime
'Mon Dec 30 21:27:03 2002'
>>> now.strftime('%Y %d %b')
'2002 30 Dec'
El método replace()
permite modificar uno o más campos de una instancia date
o datetime
, devolviendo una nueva instancia:
>>> d = datetime.datetime.now()
>>> d
datetime.datetime(2002, 12, 30, 22, 15, 38, 827738)
>>> d.replace(año=2001, hora = 12)
datetime.datetime(2001, 12, 30, 12, 15, 38, 827738)
>>>
Las instancias se pueden comparar, codificar y convertir en cadenas (el resultado es el mismo que el de isoformat()
). Las instancias date
y datetime
se pueden restar entre sí y agregar a las instancias timedelta
. La característica que falta más es que no hay compatibilidad con la biblioteca estándar para analizar cadenas y obtener un date
o datetime
.
Para obtener más información, consulte la documentación de referencia del módulo. (Contribuido por Tim Peters.)
El módulo optparse¶
El módulo getopt
proporciona un análisis sencillo de los argumentos de la línea de comandos. El nuevo módulo optparse
(originalmente llamado Optik) proporciona un análisis de línea de comandos más elaborado que sigue las convenciones de Unix, crea automáticamente la salida para --help
y puede realizar diferentes acciones para diferentes opciones.
Comienza creando una instancia de OptionParser
y diciéndole cuáles son las opciones de tu programa.
import sys
from optparse import OptionParser
op = OptionParser()
op.add_option('-i', '--input',
action='store', type='string', dest='input',
help='establecer nombre de archivo de entrada')
op.add_option('-l', '--length',
action='store', type='int', dest='length',
help='establecer longitud máxima de salida')
Luego, el análisis de una línea de comando se realiza llamando al método parse_args()
.
opciones, args = op.parse_args(sys.argv[1:])
imprimir opciones
imprimir argumentos
Esto devuelve un objeto que contiene todos los valores de las opciones y una lista de cadenas que contienen los argumentos restantes.
Invocar el script con los distintos argumentos ahora funciona como era de esperar. Tenga en cuenta que el argumento de longitud se convierte automáticamente en un número entero.
$ ./python opt.py -i data arg1
<Valores en 0x400cad4c: {'entrada': 'datos', 'longitud': Ninguno}>
['arg1']
$ ./python opt.py --input=data --length=4
<Valores en 0x400cad2c: {'entrada': 'datos', 'longitud': 4}>
[]
$
El mensaje de ayuda se genera automáticamente para usted:
$ ./python opt.py --help
uso: opt.py [opciones]
opciones:
-h, --help muestra este mensaje de ayuda y sale
-iINPUT, --input=INPUT
establece el nombre del archivo de entrada
-lLENGTH, --length=LENGTH
establece la longitud máxima de salida
$
Consulte la documentación del módulo para obtener más detalles.
Optik fue escrito por Greg Ward, con sugerencias de los lectores de Getopt SIG.
Pymalloc: un asignador de objetos especializado¶
Pymalloc, un asignador de objetos especializado escrito por Vladimir Marangozov, fue una característica agregada a Python 2.1. Pymalloc está diseñado para ser más rápido que el sistema malloc()
y tener menos sobrecarga de memoria para los patrones de asignación típicos de los programas Python. El asignador utiliza la función malloc()
de C para obtener grandes grupos de memoria y luego satisface las solicitudes de memoria más pequeñas de estos grupos.
En 2.1 y 2.2, pymalloc era una función experimental y no estaba habilitada de forma predeterminada; tenía que habilitarlo explícitamente al compilar Python proporcionando la opción --with-pymalloc
al script: program: configure. En 2.3, pymalloc ha tenido más mejoras y ahora está habilitado de forma predeterminada; tendrá que suministrar --without-pymalloc
para deshabilitarlo.
Este cambio es transparente para el código escrito en Python; sin embargo, pymalloc puede exponer errores en las extensiones C. Los autores de los módulos de extensión C deben probar su código con pymalloc habilitado, ya que algunos códigos incorrectos pueden causar volcados de núcleo en tiempo de ejecución.
Hay un error particularmente común que causa problemas. Hay una serie de funciones de asignación de memoria en la API C de Python que anteriormente solo eran alias para malloc()
y free()
de la biblioteca C, lo que significa que si llama accidentalmente a funciones que no coinciden, el error no se notará. Cuando el asignador de objetos está habilitado, estas funciones ya no son alias de malloc()
y free()
, y llamar a la función incorrecta para liberar memoria puede generar un volcado de memoria. Por ejemplo, si la memoria se asignó utilizando PyObject_Malloc()
, debe liberarse utilizando PyObject_Free()
, no free()
. Algunos módulos incluidos con Python entraron en conflicto con esto y tuvieron que ser reparados; sin duda hay más módulos de terceros que tendrán el mismo problema.
Como parte de este cambio, las confusas interfaces múltiples para asignar memoria se han consolidado en dos familias de API. La memoria asignada a una familia no debe manipularse con funciones de la otra familia. Hay una familia para asignar fragmentos de memoria y otra familia de funciones específicamente para asignar objetos Python.
Para asignar y liberar una porción de memoria no distinguida, use la familia de «memoria sin procesar»:
PyMem_Malloc()
,PyMem_Realloc()
yPyMem_Free()
.La familia de «memoria de objetos» es la interfaz para la instalación de pymalloc descrita anteriormente y está sesgada hacia un gran número de asignaciones «pequeñas»:
PyObject_Malloc()
,PyObject_Realloc()
yPyObject_Free()
.Para asignar y liberar objetos de Python, utilice la familia de «objetos»
PyObject_New
,PyObject_NewVar
yPyObject_Del()
.
Gracias al gran trabajo de Tim Peters, pymalloc en 2.3 también proporciona funciones de depuración para detectar sobrescrituras de memoria y liberaciones duplicadas en ambos módulos de extensión y en el propio intérprete. Para habilitar este soporte, compile una versión de depuración del intérprete de Python ejecutando: programa: configure con --with-pydebug
.
Para ayudar a los escritores de extensiones, se distribuye un archivo de encabezado Misc/pymemcompat.h
con la fuente a Python 2.3 que permite que las extensiones de Python usen las interfaces 2.3 para la asignación de memoria mientras se compila con cualquier versión de Python desde la 1.5.2. Debería copiar el archivo de la distribución fuente de Python y empaquetarlo con la fuente de su extensión.
Ver también
- https://hg.python.org/cpython/file/default/Objects/obmalloc.c
Para obtener todos los detalles de la implementación de pymalloc, consulte los comentarios en la parte superior del archivo
Objects/obmalloc.c
en el código fuente de Python. El enlace anterior apunta al archivo dentro del navegador SVN de python.org.
Cambios en la API de Build y C¶
Los cambios en el proceso de compilación de Python y en la API de C incluyen:
La implementación de detección de ciclos utilizada por la recolección de basura ha demostrado ser estable, por lo que ahora se ha hecho obligatoria. Ya no puede compilar Python sin él, y el cambio
--with-cycle-gc
a: program: configure ha sido eliminado.Python ahora se puede construir opcionalmente como una biblioteca compartida (
libpython2.3.so
) proporcionando--enable-shared
cuando se ejecuta el script Python: program: configure. (Contribuido por Ondrej Palkovsky.)Las macros
DL_EXPORT
yDL_IMPORT
ahora están en desuso. Las funciones de inicialización para los módulos de extensión de Python ahora deben declararse usando la nueva macroPyMODINIT_FUNC
, mientras que el núcleo de Python generalmente usará las macrosPyAPI_FUNC
yPyAPI_DATA
.El intérprete se puede compilar sin ninguna cadena de documentación para las funciones y módulos incorporados proporcionando
--without-doc-strings
al script: program: configure. Esto hace que el ejecutable de Python sea un 10% más pequeño, pero también significa que no puede obtener ayuda para las funciones integradas de Python. (Contribución de Gustavo Niemeyer.)La macro
PyArg_NoArgs()
ahora está en desuso y el código que la usa debe cambiarse. Para Python 2.2 y versiones posteriores, la tabla de definición de métodos puede especificar la marcaMETH_NOARGS
, lo que indica que no hay argumentos, y luego se puede eliminar la verificación de argumentos. Si la compatibilidad con las versiones anteriores a la 2.2 de Python es importante, el código podría usarPyArg_ParseTuple(args, "")
en su lugar, pero esto será más lento que usarMETH_NOARGS
.PyArg_ParseTuple()
acepta caracteres de nuevo formato para varios tamaños de enteros sin signo:B
para unsigned char,H
para unsigned short int,I
para unsigned int, yK
para unsigned long long.Se agregó una nueva función,
PyObject_DelItemString(mapping, char *key)
, como abreviatura dePyObject_DelItem(mapping, PyString_New(key))
.Los objetos de archivo ahora administran su búfer de cadena interno de manera diferente, incrementándolo exponencialmente cuando es necesario. Esto da como resultado que las pruebas de referencia en
Lib/test/test_bufio.py
se aceleren considerablemente (de 57 segundos a 1,7 segundos, según una medición).Ahora es posible definir métodos estáticos y de clase para un tipo de extensión C configurando los indicadores
METH_CLASS
oMETH_STATIC
en la estructuraPyMethodDef
de un método.Python ahora incluye una copia del código fuente del analizador XML de Expat, eliminando cualquier dependencia de una versión del sistema o instalación local de Expat.
Si asigna objetos de tipo de forma dinámica en su extensión, debe tener en cuenta un cambio en las reglas relacionadas con los atributos
__module__
y__name__
. En resumen, deberá asegurarse de que el diccionario del tipo contenga una clave'__module__'
; hacer que el nombre del módulo sea la parte del nombre del tipo que precede al punto final ya no tendrá el efecto deseado. Para obtener más detalles, lea la documentación de referencia de la API o el código fuente.
Cambios específicos del puerto¶
El soporte para un puerto para el sistema operativo IBM OS/2 que utiliza el entorno de ejecución EMX se fusionó con el árbol de código fuente principal de Python. EMX es una capa de emulación POSIX sobre las API del sistema OS/2. El puerto de Python para EMX intenta soportar toda la capacidad similar a POSIX expuesta por el entorno de ejecución EMX y, en su mayoría, lo logra; fork()
y fcntl()
están restringidos por las limitaciones de la capa de emulación subyacente. El puerto estándar para OS/2, que utiliza el compilador Visual Age de IBM, también obtuvo soporte para semánticas de importación que distinguen entre mayúsculas y minúsculas como parte de la integración del puerto EMX en CVS. (Contribuido por Andrew MacIntyre.)
En MacOS, la mayoría de los módulos de la caja de herramientas tienen vínculos débiles para mejorar la compatibilidad con versiones anteriores. Esto significa que los módulos ya no dejarán de cargarse si falta una rutina en la versión actual del sistema operativo. En su lugar, llamar a la rutina que falta lanzará una excepción. (Contribuido por Jack Jansen.)
Los archivos de especificaciones de RPM, que se encuentran en el directorio Misc/RPM/
en la distribución fuente de Python, se actualizaron para la versión 2.3. (Contribución de Sean Reifschneider.)
Otras plataformas nuevas ahora compatibles con Python incluyen AtheOS (http://www.atheos.cx/), GNU / Hurd y OpenVMS.
Otros cambios y correcciones¶
Como de costumbre, hubo un montón de otras mejoras y correcciones de errores esparcidas por todo el árbol de fuentes. Una búsqueda en los registros de cambios de CVS encuentra que se aplicaron 523 parches y se corrigieron 514 errores entre Python 2.2 y 2.3. Es probable que ambas cifras estén subestimadas.
Algunos de los cambios más notables son:
Si se establece la variable de entorno
PYTHONINSPECT
, el intérprete de Python ingresará al indicador interactivo después de ejecutar un programa de Python, como si Python hubiera sido invocado con la opción-i
. La variable de entorno se puede configurar antes de ejecutar el intérprete de Python, o el programa Python puede configurarla como parte de su ejecución.El script
regrtest.py
ahora proporciona una forma de permitir «todos los recursos excepto foo». Un nombre de recurso pasado a la opción-u
ahora se puede prefijar con un guión ('-'
) para significar «eliminar este recurso». Por ejemplo, la opción “-uall,-bsddb
” podría usarse para habilitar el uso de todos los recursos exceptobsddb
.Las herramientas utilizadas para crear la documentación ahora funcionan tanto en Cygwin como en Unix.
Se ha eliminado el código de operación
SET_LINENO
. En la noche de los tiempos, este código de operación era necesario para producir números de línea en rastreos y admitir funciones de rastreo (para, por ejemplo,pdb
). Desde Python 1.5, los números de línea en los rastreos se han calculado utilizando un mecanismo diferente que funciona con «python -O». Para Python 2.3, Michael Hudson implementó un esquema similar para determinar cuándo llamar a la función de seguimiento, eliminando por completo la necesidad deSET_LINENO
.Sería difícil detectar cualquier diferencia resultante del código Python, aparte de una ligera aceleración cuando Python se ejecuta sin
-O
.Las extensiones de C que acceden al campo
f_lineno
de los objetos de marco deberían llamar aPyCode_Addr2Line(f->f_code, f->f_lasti)
. Esto tendrá el efecto adicional de hacer que el código funcione como se desea con «python -O» en versiones anteriores de Python.Una característica nueva y elegante es que las funciones de seguimiento ahora pueden asignarse al atributo
f_lineno
de los objetos de marco, lo que cambia la línea que se ejecutará a continuación. Se ha agregado un comandojump
al depuradorpdb
que aprovecha esta nueva característica. (Implementado por Richie Hindle).
Portar a Python 2.3¶
Esta sección enumera los cambios descritos anteriormente que pueden requerir cambios en su código:
yield
ahora es siempre una palabra clave; si se usa como nombre de variable en su código, se debe elegir un nombre diferente.Para cadenas, X and Y, ASDF00 now works if X tiene más de un carácter.
El constructor de tipo
int()
ahora retornará un entero largo en lugar de lanzar unOverflowError
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 queisinstance(int(expresión), int)
sea falso, pero parece poco probable que cause problemas en la práctica.Si tiene cadenas Unicode que contienen caracteres de 8 bits, debe declarar la codificación del archivo (UTF-8, Latin-1 o lo que sea) agregando un comentario en la parte superior del archivo. Consulte la sección PEP 263: Codificación del código fuente para obtener más información.
La llamada a métodos Tcl a través de
_tkinter
ya no devuelve solo cadenas. En cambio, si Tcl devuelve otros objetos, esos objetos se convierten en su equivalente de Python, si existe uno, o se encapsulan con un objeto_tkinter.Tcl_Obj
si no existe un equivalente de Python.Grandes literales octales y hexadecimales como
0xffffffff
ahora activan unFutureWarning
. Actualmente se almacenan como números de 32 bits y dan como resultado un valor negativo, pero en Python 2.4 se convertirán en enteros largos positivos.Hay varias formas de corregir esta advertencia. Si realmente necesita un número positivo, simplemente agregue un
L
al final del literal. Si está tratando de obtener un entero de 32 bits con bits bajos establecidos y ha usado previamente una expresión como~(1 << 31)
, probablemente sea más claro comenzar con todos los bits establecidos y borrar los bits superiores deseados. Por ejemplo, para borrar solo el bit superior (bit 31), puede escribir0xffffffffL &~(1L<<31)
.Ya no puede deshabilitar las aserciones asignando a
__debug__
.La función
setup()
de Distutils ha obtenido varios argumentos de palabras clave nuevos, como depends. Las versiones anteriores de Distutils se interrumpirán si se les pasan palabras clave desconocidas. Una solución es comprobar la presencia de la nueva funciónget_distutil_options()
en susetup.py
y utilizar las nuevas palabras clave solo con una versión de Distutils que las admita:from distutils import core kw = {'sources': 'foo.c', ...} if hasattr(core, 'get_distutil_options'): kw['depends'] = ['foo.h'] ext = Extension(**kw)
El uso de
None
como nombre de una variable ahora resultará en una advertenciaSyntaxWarning
. En una futura versión de Python,None
podría convertirse en una palabra clave.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.
Agradecimientos¶
El autor desea agradecer a las siguientes personas por ofrecer sugerencias, correcciones y ayuda con varios borradores de este artículo: 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.