Qué hay de nuevo en Python 2.5
En esta página
- PEP 308: Expresiones condicionales#
- PEP 309: Aplicación parcial de funciones#
- PEP 314: Metadatos para paquetes de software Python v1.1#
- PEP 328: Importaciones absolutas y relativas#
- PEP 338: Ejecutando Módulos como Scripts#
- PEP 341: Try/except/finally unificados#
- PEP 342: Nuevas funciones del generador#
- PEP 343: La declaración "con#
- Redacción de Gestores de Contexto#
- El módulo contextlib#
- PEP 352: Las excepciones como clases de nuevo estilo#
- PEP 353: Uso de ssize_t como tipo de índice#
- PEP 357: El método 'index'#
- Otros cambios lingüísticos#
- Cambios en el intérprete interactivo#
- Optimizaciones#
- Módulos nuevos, mejorados y eliminados#
- El paquete ctypes#
- El paquete ElementTree#
- | "elem[n]" | Devuelve el elemento hijo enésimo. |#
- | | hijos. |#
- | "len(elem)" | Devuelve el número de elementos hijos. |#
- | "lista(elem)" | Devuelve la lista de elementos hijos. |#
- | "elem.append(elem2)" | Añade elemento2 como hijo. |#
- | | especificado. |#
- | "del elem[n]" | Elimina el elemento hijo enésimo. |#
- | "elem.keys()" | Devuelve la lista de nombres de atributos. |#
- | "elem.get(name)" | Devuelve el valor del atributo nombre. |#
- | | nombre. |#
- | | atributos. |#
- | "del elem.attrib[name]" | Borra el atributo nombre. |#
- El paquete hashlib#
- El paquete sqlite3#
- El paquete wsgiref#
- Cambios en la API de construcción y C#
- Cambios específicos en los puertos#
- Adaptación a Python 2.5#
- Agradecimientos#
Qué hay de nuevo en Python 2.5#
Autor: A.M. Kuchling
Este artículo explica las nuevas características de Python 2.5. La versión final de Python 2.5 está prevista para agosto de 2006; PEP 356 describe el cronograma de lanzamiento planificado.
The changes in Python 2.5 are an interesting mix of language and library improvements. The library enhancements will be more important to Python's user community, I think, because several widely useful packages were added. New modules include ElementTree for XML processing ("xml.etree.ElementTree"), the SQLite database module ("sqlite3"), and the "ctypes" module for calling C functions.
Los cambios en el lenguaje son de mediana importancia. Se han añadido algunas características nuevas y agradables, pero la mayoría de ellas no son características que vaya a utilizar todos los días. Las expresiones condicionales fueron finalmente añadidas al lenguaje usando una nueva sintaxis; ver sección PEP 308: Expresiones condicionales. La nueva sentencia '"with"' facilitará la escritura de código de limpieza (sección PEP 343: La declaración "con). Ahora se pueden pasar valores a los generadores (sección PEP 342: Nuevas funciones del generador). Las importaciones son ahora visibles como absolutas o relativas (sección PEP 328: Importaciones absolutas y relativas). Se han mejorado algunos casos de manejo de excepciones (sección PEP 341: Try/except/finally unificados). Todas estas mejoras merecen la pena, pero son mejoras de una u otra característica específica del lenguaje; ninguna de ellas es una modificación amplia de la semántica de Python.
Además de las adiciones al lenguaje y a la biblioteca, se han realizado otras mejoras y correcciones de errores en todo el árbol de código fuente. Una búsqueda en los registros de cambios del SVN revela que se aplicaron 353 parches y se corrigieron 458 errores entre Python 2.4 y 2.5. (Es probable que ambas cifras estén subestimadas)
Este artículo no pretende ser una especificación completa de las nuevas características; en su lugar, los cambios se introducen brevemente utilizando ejemplos útiles. Para obtener todos los detalles, siempre debes consultar la documentación de Python 2.5 en https://docs.python.org. Si quieres entender la implementación completa y los fundamentos del diseño, consulta el PEP de una nueva característica en particular.
Son bienvenidos los comentarios, las sugerencias y los informes de errores para este documento; por favor, envíelos por correo electrónico al autor o abra un error en el rastreador de errores de Python.
PEP 308: Expresiones condicionales#
Durante mucho tiempo, la gente ha solicitado una forma de escribir expresiones condicionales, que son expresiones que devuelven el valor A o el valor B dependiendo de si un valor booleano es verdadero o falso. Una expresión condicional le permite escribir una única sentencia de asignación que tiene el mismo efecto que la siguiente:
Si la condición es: x = valor_verdadero De lo contrario: x = valor_falso
Ha habido interminables y tediosas discusiones sobre la sintaxis tanto en python-dev como en comp.lang.python. Incluso se llevó a cabo una votación en la que se descubrió que la mayoría de los votantes querían expresiones condicionales de alguna forma, pero no había ninguna sintaxis que fuera preferida por una clara mayoría. Los candidatos incluían "cond ? true_v : false_v", "if cond then true_v else false_v", y otras 16 variaciones.
Guido van Rossum eligió finalmente una sintaxis sorprendente:
x = valor_verdadero si condición de lo contrario valor_falso
La evaluación sigue siendo perezosa como en las expresiones booleanas existentes, por lo que el orden de evaluación salta un poco. La expresión condición del medio se evalúa primero, y la expresión valor_verdadero se evalúa sólo si la condición es verdadera. Del mismo modo, la expresión valor_falso sólo se evalúa cuando la condición es falsa.
Esta sintaxis puede parecer extraña y retrógrada; ¿por qué la condición va en el medio de la expresión, y no en la parte delantera como en "c ? x : y" de C? La decisión se comprobó aplicando la nueva sintaxis a los módulos de la biblioteca estándar y viendo cómo se leía el código resultante. En muchos casos en los que se utiliza una expresión condicional, un valor parece ser el "caso común" y otro valor es un "caso excepcional", utilizado sólo en las raras ocasiones en las que no se cumple la condición. La sintaxis condicional hace que este patrón sea un poco más obvio:
contenido = ((doc + '\n') si doc si no '')
Leo la afirmación anterior en el sentido de que "aquí se asigna a contents un valor de "doc+'\n'"; a veces doc está vacío, en cuyo caso especial se devuelve una cadena vacía" Dudo que use expresiones condicionales muy a menudo donde no hay un caso común y no común claro.
Hubo alguna discusión sobre si el lenguaje debería requerir rodear las expresiones condicionales con paréntesis. Se tomó la decisión de no requerir paréntesis en la gramática del lenguaje Python, pero como una cuestión de estilo creo que siempre deberías usarlos. Considere estas dos declaraciones:
# Primera versión: sin paréntesis nivel = 1 si se registra, de lo contrario, 0
# Segunda versión: con paréntesis nivel = (1 si se registra, de lo contrario, 0)
En la primera versión, creo que el ojo de un lector podría agrupar la sentencia en 'nivel = 1', 'si registro', 'si no 0', y pensar que la condición decide si se realiza la asignación a nivel. La segunda versión se lee mejor, en mi opinión, porque deja claro que la asignación se realiza siempre y que se está eligiendo entre dos valores.
Otra razón para incluir los paréntesis: algunas combinaciones extrañas de comprensiones de listas y lambdas podrían parecer expresiones condicionales incorrectas. Véase PEP 308 para algunos ejemplos. Si pone paréntesis alrededor de sus expresiones condicionales, no se encontrará con este caso.
Ver también:
PEP 308 - Expresiones condicionales PEP escrito por Guido van Rossum y Raymond D. Hettinger; implementado por Thomas Wouters.
PEP 309: Aplicación parcial de funciones#
El módulo "functools" está destinado a contener herramientas para la programación de estilo funcional.
One useful tool in this module is the "partial()" function. For programs written in a functional style, you'll sometimes want to construct variants of existing functions that have some of the parameters filled in. Consider a Python function "f(a, b, c)"; you could create a new function "g(b, c)" that was equivalent to "f(1, b, c)". This is called "partial function application".
"partial()" takes the arguments "(function, arg1, arg2, ... kwarg1=value1, kwarg2=value2)". The resulting object is callable, so you can just call it to invoke function with the filled-in arguments.
He aquí un pequeño pero realista ejemplo:
import functools
def log (message, subsystem): "Escribe el contenido de 'message' en el subsistema especificado". print '%s: %s' % (subsystem, message) ...
server_log = functools.partial(log, subsystem='server') server_log('No se puede abrir el socket')
Here's another example, from a program that uses PyGTK. Here a context-sensitive pop-up menu is being constructed dynamically. The callback provided for the menu option is a partially applied version of the "open_item()" method, where the first argument has been provided.
... class Application: def open_item(self, path): ... def init (self): open_func = functools.partial(self.open_item, item_path) popup_menu.append( ("Open", open_func, 1) )
Another function in the "functools" module is the "update_wrapper(wrapper, wrapped)" function that helps you write well- behaved decorators. "update_wrapper()" copies the name, module, and docstring attribute to a wrapper function so that tracebacks inside the wrapped function are easier to understand. For example, you might write:
def my_decorator(f): def wrapper(args, kwds): print 'Calling decorated function' return f(args, **kwds) functools.update_wrapper(wrapper, f) return wrapper
"wraps()" is a decorator that can be used inside your own decorators to copy the wrapped function's information. An alternate version of the previous example would be:
def my_decorator(f): @functools.wraps(f) def wrapper(args, kwds): print 'Calling decorated function' return f(args, **kwds) return wrapper
Ver también:
PEP 309 - Aplicación parcial de funciones PEP propuesto y escrito por Peter Harris; implementado por Hye- Shik Chang y Nick Coghlan, con adaptaciones de Raymond Hettinger.
PEP 314: Metadatos para paquetes de software Python v1.1#
Some simple dependency support was added to Distutils. The "setup()" function now has "requires", "provides", and "obsoletes" keyword parameters. When you build a source distribution using the "sdist" command, the dependency information will be recorded in the "PKG-INFO" file.
Otro nuevo parámetro de palabra clave es "download_url", que debe establecerse como una URL para el código fuente del paquete. Esto significa que ahora es posible buscar una entrada en el índice de paquetes, determinar las dependencias de un paquete y descargar los paquetes necesarios.
VERSION = '1.0' setup(name='PyPackage', version=VERSION, requires=['numarray', 'zlib (>=1.1.4)'], obsoletes=['OldPackage'] download_url=('http://www.example.com/pypackage/dist/pkg-%s.tar.gz' % VERSION), )
Otra nueva mejora en el índice de paquetes de Python en https://pypi.org es el almacenamiento de archivos fuente y binarios de un paquete. El nuevo comando upload de Distutils subirá un paquete al repositorio.
Antes de poder subir un paquete, debes ser capaz de construir una distribución usando el comando sdist de Distutils. Una vez que funcione, puedes ejecutar "python setup.py upload" para añadir tu paquete al archivo PyPI. Opcionalmente puedes firmar el paquete con GPG suministrando las opciones "--sign" y "--identity".
La carga de paquetes fue implementada por Martin von Löwis y Richard Jones.
Ver también:
PEP 314 - Metadatos para paquetes de software Python v1.1 PEP propuesto y redactado por A.M. Kuchling, Richard Jones y Fred Drake; aplicado por Richard Jones y Fred Drake.
PEP 328: Importaciones absolutas y relativas#
La parte más sencilla de PEP 328 se implementó en Python 2.4: los paréntesis podían utilizarse ahora para encerrar los nombres importados de un módulo utilizando la sentencia "from ... import ...", facilitando la importación de muchos nombres diferentes.
La parte más complicada se ha implementado en Python 2.5: la importación de un módulo puede especificarse para utilizar importaciones absolutas o relativas al paquete. El plan es hacer que las importaciones absolutas sean el valor por defecto en futuras versiones de Python.
Digamos que tienes un directorio de paquetes como este:
pkg/ pkg/init.py pkg/main.py pkg/string.py
This defines a package named "pkg" containing the "pkg.main" and "pkg.string" submodules.
Consider the code in the "main.py" module. What happens if it executes the statement "import string"? In Python 2.4 and earlier, it will first look in the package's directory to perform a relative import, finds "pkg/string.py", imports the contents of that file as the "pkg.string" module, and that module is bound to the name "string" in the "pkg.main" module's namespace.
That's fine if "pkg.string" was what you wanted. But what if you wanted Python's standard "string" module? There's no clean way to ignore "pkg.string" and look for the standard module; generally you had to look at the contents of "sys.modules", which is slightly unclean. Holger Krekel's "py.std" package provides a tidier way to perform imports from the standard library, "import py; py.std.string.join()", but that package isn't available on all Python installations.
Reading code which relies on relative imports is also less clear, because a reader may be confused about which module, "string" or "pkg.string", is intended to be used. Python users soon learned not to duplicate the names of standard library modules in the names of their packages' submodules, but you can't protect against having your submodule's name being used for a new module added in a future version of Python.
En Python 2.5, puedes cambiar el comportamiento de "import" a importaciones absolutas usando una directiva "from future import absolute_import". Este comportamiento de importación absoluta será el predeterminado en una versión futura (probablemente Python 2.7). Una vez que las importaciones absolutas sean el valor por defecto, "import string" siempre encontrará la versión de la biblioteca estándar. Se sugiere que los usuarios comiencen a usar importaciones absolutas tanto como sea posible, así que es preferible comenzar a escribir "de pkg import string" en su código.
Las importaciones relativas siguen siendo posibles añadiendo un punto inicial al nombre del módulo cuando se utiliza la forma "from ... import":
# Import names from pkg.string from .string import name1, name2 # Import pkg.string from . import string
This imports the "string" module relative to the current package, so in "pkg.main" this will import name1 and name2 from "pkg.string". Additional leading periods perform the relative import starting from the parent of the current package. For example, code in the "A.B.C" module can do:
from . import D # Imports A.B.D from .. import E # Imports A.E from ..F import G # Imports A.F.G
Los puntos suspensivos no pueden usarse con la forma "importar nombre de modelo" de la sentencia import, sólo con la forma "de ... import".
Ver también:
PEP 328 - Importaciones: Multilínea y Absoluto/Relativo PEP escrito por Aahz; implementado por Thomas Wouters.
https://pylib.readthedocs.io/ The py library by Holger Krekel, which contains the "py.std" package.
PEP 338: Ejecutando Módulos como Scripts#
El conmutador "-m" añadido en Python 2.4 para ejecutar un módulo como un script ganó algunas habilidades más. En lugar de estar implementado en código C dentro del intérprete de Python, el interruptor ahora utiliza una implementación en un nuevo módulo, "runpy".
The "runpy" module implements a more sophisticated import mechanism so that it's now possible to run modules in a package such as "pychecker.checker". The module also supports alternative import mechanisms such as the "zipimport" module. This means you can add a .zip archive's path to "sys.path" and then use the "-m" switch to execute code from the archive.
Ver también:
PEP 338 - Ejecución de módulos como scripts PEP escrito e implementado por Nick Coghlan.
PEP 341: Try/except/finally unificados#
Hasta la versión 2.5 de Python, la sentencia "try" tenía dos variantes. Podías usar un bloque "finally" para asegurarte de que el código se ejecutaba siempre, o uno o más bloques "except" para capturar excepciones específicas. No podías combinar ambos bloques "except" y un bloque "finally", porque generar el bytecode correcto para la versión combinada era complicado y no estaba claro cuál debía ser la semántica de la sentencia combinada.
Guido van Rossum pasó algún tiempo trabajando con Java, que sí soporta el equivalente de combinar bloques "except" y un bloque "finally", y esto aclaró lo que debería significar la declaración. En Python 2.5, ahora se puede escribir:
try: block-1 ... except Exception1: handler-1 ... except Exception2: handler-2 ... else: else-block finally: final-block
The code in block-1 is executed. If the code raises an exception, the various "except" blocks are tested: if the exception is of class "Exception1", handler-1 is executed; otherwise if it's of class "Exception2", handler-2 is executed, and so forth. If no exception is raised, the else-block is executed.
No importa lo que haya sucedido previamente, el bloque final se ejecuta una vez que el bloque de código se ha completado y se han manejado las excepciones planteadas. Incluso si hay un error en un manejador de excepciones o en el bloque else y se lanza una nueva excepción, el código del bloque final se sigue ejecutando.
Ver también:
PEP 341 - Unificar try-except y try-finally PEP escrito por Georg Brandl; implementación por Thomas Lee.
PEP 342: Nuevas funciones del generador#
Python 2.5 añade una forma sencilla de pasar valores a un generador. Tal y como se introdujo en Python 2.3, los generadores sólo producen salida; una vez que se invoca el código de un generador para crear un iterador, no hay forma de pasar ninguna información nueva a la función cuando se reanuda su ejecución. A veces, la capacidad de pasar alguna información sería útil. Las soluciones más ingeniosas para esto incluyen hacer que el código del generador mire a una variable global y luego cambie el valor de la variable global, o pasar algún objeto mutable que los llamadores luego modifiquen.
Para refrescar la memoria de los generadores básicos, he aquí un ejemplo sencillo:
def counter (maximum): i = 0 while i < maximum: yield i i += 1
Cuando se llama a "contador(10)", el resultado es un iterador que devuelve los valores de 0 a 9. Al encontrar la sentencia "yield", el iterador devuelve el valor proporcionado y suspende la ejecución de la función, preservando las variables locales. La ejecución se reanuda en la siguiente llamada al método "next()" del iterador, retomando después de la sentencia "yield".
En Python 2.3, "yield" era una declaración; no devolvía ningún valor. En 2.5, "yield" es ahora una expresión, que devuelve un valor que se puede asignar a una variable o que se puede operar de otra manera:
val = (rendimiento i)
Te recomiendo que siempre pongas paréntesis alrededor de una expresión "yield" cuando estés haciendo algo con el valor devuelto, como en el ejemplo anterior. Los paréntesis no siempre son necesarios, pero es más fácil añadirlos siempre en lugar de tener que recordar cuándo son necesarios.
(PEP 342 explica las reglas exactas, que consisten en que una expresión "yield"debe ir siempre entre paréntesis, excepto cuando ocurre en la expresión de nivel superior en el lado derecho de una asignación. Esto significa que puedes escribir "val = yield i" pero tienes que usar paréntesis cuando hay una operación, como en "val = (yield i) + 12")
Los valores se envían a un generador llamando a su método "send(value)". El código del generador se reanuda y la expresión "yield" devuelve el valor especificado. Si se llama al método regular "next()", la expresión "yield" devuelve "None".
Aquí está el ejemplo anterior, modificado para permitir cambiar el valor del contador interno.
def counter (maximum): i = 0 while i < maximum: val = (yield i) # If value provided, change counter if val is not None: i = val else: i += 1
Y aquí hay un ejemplo de cambio de contador:
it = counter(10) print it.next() 0 print it.next() 1 print it.send(8) 8 print it.next() 9 print it.next() Traceback (most recent call last): File "t.py", line 15, in ? print it.next() StopIteration
"yield" will usually return "None", so you should always check for this case. Don't just use its value in expressions unless you're sure that the "send()" method will be the only method used to resume your generator function.
In addition to "send()", there are two other new methods on generators:
-
"throw(type, value=None, traceback=None)" se utiliza para lanzar una excepción dentro del generador; la excepción es lanzada por la expresión "yield" donde la ejecución del generador se pausa.
-
"close()" raises a new "GeneratorExit" exception inside the generator to terminate the iteration. On receiving this exception, the generator's code must either raise "GeneratorExit" or "StopIteration". Catching the "GeneratorExit" exception and returning a value is illegal and will trigger a "RuntimeError"; if the function raises some other exception, that exception is propagated to the caller. "close()" will also be called by Python's garbage collector when the generator is garbage-collected.
Si necesitas ejecutar código de limpieza cuando se produce un "GeneratorExit", te sugiero que utilices un conjunto "try: ... finally:" en lugar de atrapar "GeneratorExit".
El efecto acumulativo de estos cambios es que los generadores pasan de ser productores unidireccionales de información a ser tanto productores como consumidores.
Los generadores también se convierten en corutinas, una forma más generalizada de subrutinas. Las subrutinas se introducen en un punto y se salen en otro (la parte superior de la función, y una declaración "return"), pero las coroutines pueden introducirse, salirse y reanudarse en muchos puntos diferentes (las declaraciones "yield"). Tendremos que descubrir patrones para usar coroutines de forma efectiva en Python.
The addition of the "close()" method has one side effect that isn't obvious. "close()" is called when a generator is garbage-collected, so this means the generator's code gets one last chance to run before the generator is destroyed. This last chance means that "try...finally" statements in generators can now be guaranteed to work; the "finally" clause will now always get a chance to run. The syntactic restriction that you couldn't mix "yield" statements with a "try...finally" suite has therefore been removed. This seems like a minor bit of language trivia, but using generators and "try...finally" is actually necessary in order to implement the "with" statement described by PEP 343. I'll look at this new statement in the following section.
Another even more esoteric effect of this change: previously, the "gi_frame" attribute of a generator was always a frame object. It's now possible for "gi_frame" to be "None" once the generator has been exhausted.
Ver también:
PEP 342 - Coroutines mediante generadores mejorados PEP escrito por Guido van Rossum y Phillip J. Eby; implementado por Phillip J. Eby. Incluye ejemplos de algunos usos más sofisticados de los generadores como coroutines.
Versiones anteriores de estas características fueron propuestas
en **PEP 288** por Raymond Hettinger y **PEP 325** por Samuele
Pedroni.
https://en.wikipedia.org/wiki/Coroutine La entrada de Wikipedia para las coroutines.
https://web.archive.org/web/20160321211320/http://www.sidhe.org/~da n/blog/archives/000178.html Una explicación de las coroutines desde el punto de vista de Perl, escrita por Dan Sugalski.
PEP 343: La declaración "con#
La sentencia '"with"' aclara el código que antes utilizaba bloques "try...finally"' para asegurar que se ejecuta el código de limpieza. En esta sección, hablaré de la sentencia tal y como se utiliza habitualmente. En la siguiente sección, examinaré los detalles de la implementación y mostraré cómo escribir objetos para usar con esta sentencia.
La declaración '"with"' es una nueva estructura de flujo de control cuya estructura básica es:
with expression [as variable]: with-block
Se evalúa la expresión y debería dar como resultado un objeto que admita el protocolo de gestión de contexto (es decir, que tenga los métodos "enter()" y "exit()").
El objeto "enter()" se llama antes de que se ejecute with-block y, por lo tanto, puede ejecutar el código de configuración. También puede devolver un valor vinculado al nombre variable, si se proporciona. (Tenga en cuenta que variable es not al que se le asigna el resultado de expression).
Una vez finalizada la ejecución de with-block, se llama al método "exit()" del objeto, incluso si el bloque generó una excepción y, por lo tanto, puede ejecutar código de limpieza.
Para habilitar la declaración en Python 2.5, debe añadir la siguiente directiva a su módulo:
desde future importar con_declaración
La declaración siempre estará habilitada en Python 2.6.
Algunos objetos estándar de Python soportan ahora el protocolo de gestión de contextos y pueden utilizarse con la sentencia '"with"''. Los objetos de archivo son un ejemplo:
with open('/etc/passwd', 'r') as f: for line in f: print line ... more processing code ...
Después de que esta sentencia se haya ejecutado, el objeto archivo en f se habrá cerrado automáticamente, incluso si el bucle "for" lanzó una excepción a mitad del bloque.
Nota:
En este caso, f es el mismo objeto creado por "open()", porque "enter()" devuelve self.
Los bloqueos y las variables de condición del módulo "threading" también soportan la sentencia '"with"':
lock = threading.Lock() with lock: # Critical section of code ...
El bloqueo se adquiere antes de que se ejecute el bloque y siempre se libera una vez que el bloque se ha completado.
The new "localcontext()" function in the "decimal" module makes it easy to save and restore the current decimal context, which encapsulates the desired precision and rounding characteristics for computations:
from decimal import Decimal, Context, localcontext
# Displays with default precision of 28 digits v = Decimal('578') print v.sqrt()
with localcontext(Context(prec=16)): # All code in this block uses a precision of 16 digits. # The original context is restored on exiting the block. print v.sqrt()
Redacción de Gestores de Contexto#
Bajo el capó, la sentencia '"with"' es bastante complicada. La mayoría de la gente sólo utilizará '"with"' en compañía de objetos existentes y no necesita conocer estos detalles, así que puedes saltarte el resto de esta sección si quieres. Los autores de nuevos objetos necesitarán entender los detalles de la implementación subyacente y deberían seguir leyendo.
Una explicación de alto nivel del protocolo de gestión del contexto es:
-
La expresión se evalúa y debería generar un objeto denominado "administrador de contexto". El administrador de contexto debe tener los métodos "enter()" y "exit()".
-
Se llama al método "enter()" del administrador de contexto. El valor devuelto se asigna a VAR. Si no hay ninguna cláusula "'as VAR'", el valor simplemente se descarta.
-
Se ejecuta el código en BLOQUE.
-
Si BLOCK lanza una excepción, se llama a "exit(type, value, traceback)" con los detalles de la excepción, los mismos valores devueltos por "sys.exc_info()". El valor de retorno del método controla si la excepción se vuelve a lanzar: cualquier valor falso vuelve a lanzar la excepción, y "True" resultará en suprimirla. Sólo en raras ocasiones querrá suprimir la excepción, porque si lo hace el autor del código que contiene la declaración '"with"' nunca se dará cuenta de que algo ha ido mal.
-
Si BLOCK no generó una excepción, aún se llama al método "exit()", pero type, value y traceback son todos "None".
Pensemos en un ejemplo. No presentaré un código detallado, sino que sólo esbozaré los métodos necesarios para una base de datos que soporte transacciones.
(Para quienes no estén familiarizados con la terminología de las bases de datos: un conjunto de cambios en la base de datos se agrupa en una transacción. Las transacciones pueden ser confirmadas, lo que significa que todos los cambios se escriben en la base de datos, o revertidas, lo que significa que todos los cambios se descartan y la base de datos no se modifica. Consulte cualquier libro de texto sobre bases de datos para obtener más información)
Supongamos que hay un objeto que representa una conexión a la base de datos. Nuestro objetivo será permitir que el usuario escriba código como este:
db_connection = DatabaseConnection() with db_connection as cursor: cursor.execute('insert into ...') cursor.execute('delete from ...') # ... more operations ...
The transaction should be committed if the code in the block runs flawlessly or rolled back if there's an exception. Here's the basic interface for "DatabaseConnection" that I'll assume:
class DatabaseConnection: # Database interface def cursor (self): "Returns a cursor object and starts a new transaction" def commit (self): "Commits current transaction" def rollback (self): "Rolls back current transaction"
El método "enter()" es bastante sencillo, ya que solo hay que iniciar una nueva transacción. Para esta aplicación, el objeto cursor resultante sería un resultado útil, por lo que el método lo devolverá. El usuario puede entonces añadir "as cursor" a su declaración '"with"' para vincular el cursor a un nombre de variable.
class DatabaseConnection: ... def enter (self): # Code to start a new transaction cursor = self.cursor() return cursor
El método "exit()" es el más complicado porque es donde se debe realizar la mayor parte del trabajo. El método debe verificar si se produjo una excepción. Si no hubo excepción, se confirma la transacción. Si hubo una excepción, se revierte la transacción.
En el código de abajo, la ejecución simplemente caerá al final de la función, devolviendo el valor por defecto de "None". "None" es falso, por lo que la excepción se volverá a lanzar automáticamente. Si lo desea, puede ser más explícito y añadir una declaración "return" en el lugar marcado.
class DatabaseConnection: ... def exit (self, type, value, tb): if tb is None: # No exception, so commit self.commit() else: # Exception occurred, so rollback. self.rollback() # return False
El módulo contextlib#
El nuevo módulo "contextlib" proporciona algunas funciones y un decorador que son útiles para escribir objetos para usar con la sentencia '"with"'.
The decorator is called "@~contextlib.contextmanager", and lets you write a single generator function instead of defining a new class. The generator should yield exactly one value. The code up to the "yield" will be executed as the "enter()" method, and the value yielded will be the method's return value that will get bound to the variable in the '"with"' statement's "as" clause, if any. The code after the "yield" will be executed in the "exit()" method. Any exception raised in the block will be raised by the "yield" statement.
Nuestro ejemplo de base de datos de la sección anterior podría escribirse utilizando este decorador como:
from contextlib import contextmanager
@contextmanager def db_transaction (connection): cursor = connection.cursor() try: yield cursor except: connection.rollback() raise else: connection.commit()
db = DatabaseConnection() with db_transaction(db) as cursor: ...
El módulo "contextlib" también tiene una función "anidada(mgr1, mgr2, ...)" que combina varios gestores de contexto para que no sea necesario escribir sentencias '"with"' anidadas. En este ejemplo, la única sentencia '"with`" inicia una transacción de base de datos y adquiere un bloqueo de hilo:
lock = threading.Lock() con anidado (db_transaction(db), lock) como (cursor, bloqueado): ...
Por último, la función "closing(object)" devuelve el objeto para que pueda ser vinculado a una variable, y llama a "object.close" al final del bloque.
import urllib, sys from contextlib import closing
with closing(urllib.urlopen('http://www.yahoo.com')) as f: for line in f: sys.stdout.write(line)
Ver también:
PEP 343 - La declaración "con" PEP escrito por Guido van Rossum y Nick Coghlan; implementado por Mike Bland, Guido van Rossum y Neal Norwitz. El PEP muestra el código generado para una sentencia '"with"', que puede ser útil para aprender cómo funciona la sentencia.
La documentación del módulo "contextlib".
PEP 352: Las excepciones como clases de nuevo estilo#
Las clases de excepción ahora pueden ser clases de nuevo estilo, no sólo clases clásicas, y la clase incorporada "Exception" y todas las excepciones incorporadas estándar ("NameError", "ValueError", etc.) son ahora clases de nuevo estilo.
La jerarquía de herencia de las excepciones se ha reordenado un poco. En 2.5, las relaciones de herencia son:
BaseException # New in Python 2.5 |- KeyboardInterrupt |- SystemExit |- Exception |- (all other current built-in exceptions)
Esta reorganización se hizo porque la gente a menudo quiere atrapar todas las excepciones que indican errores del programa. "KeyboardInterrupt" y "SystemExit" no son errores, sin embargo, y por lo general representan una acción explícita como el usuario pulsando "Control"-"C" o el código llamando a "sys.exit()". Una simple "except:" atrapará todas las excepciones, por lo que comúnmente se necesita listar "KeyboardInterrupt" y "SystemExit" para volver a lanzarlas. El patrón habitual es:
try: ... except (KeyboardInterrupt, SystemExit): raise except: # Log error... # Continue running program...
En Python 2.5, ahora puedes escribir "except Exception" para conseguir el mismo resultado, capturando todas las excepciones que suelen indicar errores pero dejando "KeyboardInterrupt" y "SystemExit" en paz. Como en versiones anteriores, un "except:" desnudo sigue capturando todas las excepciones.
El objetivo de Python 3.0 es requerir que cualquier clase lanzada como excepción derive de "BaseException" o de algún descendiente de "BaseException", y las futuras versiones de la serie Python 2.x pueden empezar a imponer esta restricción. Por lo tanto, sugiero que empieces a hacer que todas tus clases de excepción deriven de "Exception" ahora. Se ha sugerido que la forma desnuda "except:" sea eliminada en Python 3.0, pero Guido van Rossum no ha decidido si hacerlo o no.
El lanzamiento de cadenas como excepciones, como en la declaración "raise "Error occurred"", está obsoleto en Python 2.5 y provocará una advertencia. El objetivo es poder eliminar la función de excepción de cadena en algunas versiones.
Ver también:
PEP 352 - Superclase necesaria para las excepciones PEP escrito por Brett Cannon y Guido van Rossum; implementado por Brett Cannon.
PEP 353: Uso de ssize_t como tipo de índice#
Un cambio de gran alcance en la API C de Python, que usa una nueva definición de tipo "Py_ssize_t" en lugar de int, permitirá que el intérprete maneje más datos en plataformas de 64 bits. Este cambio no afecta la capacidad de Python en plataformas de 32 bits.
Varias piezas del intérprete de Python usaban el tipo int de C para almacenar tamaños o conteos; por ejemplo, la cantidad de elementos en una lista o tupla se almacenaron en un int. Los compiladores de C para la mayoría de las plataformas de 64 bits aún definen int como un tipo de 32 bits, lo que significa que las listas solo pueden contener hasta "2**31 - 1" = 2147483647 elementos. (En realidad, hay algunos modelos de programación diferentes que los compiladores de C de 64 bits pueden usar; consulte https://unix.org/version2/whatsnew/lp64_wp.html para ver una discusión, pero el modelo más comúnmente disponible deja int como 32 bits).
Un límite de 2147483647 elementos no importa realmente en una plataforma de 32 bits porque te quedarás sin memoria antes de alcanzar el límite de longitud. Cada elemento de la lista requiere espacio para un puntero, que es de 4 bytes, más espacio para un "PyObject" que representa el elemento. 2147483647*4 ya son más bytes de los que puede contener un espacio de direcciones de 32 bits.
Sin embargo, es posible abordar esa cantidad de memoria en una plataforma de 64 bits. Los punteros para una lista de ese tamaño solo requerirían 16 GiB de espacio, por lo que no es irrazonable que los programadores de Python puedan construir listas tan grandes. Por lo tanto, el intérprete de Python tuvo que cambiarse para usar algún tipo diferente a int, y este será un tipo de 64 bits en plataformas de 64 bits. El cambio provocará incompatibilidades en las máquinas de 64 bits, por lo que se consideró que valía la pena hacer la transición ahora, mientras que la cantidad de usuarios de 64 bits aún es relativamente pequeña. (En 5 o 10 años, es posible que todo esté en máquinas de 64 bits y la transición sería más dolorosa entonces).
Este cambio afecta en mayor medida a los autores de módulos de extensión de C. Las cadenas de Python y los tipos contenedores como las listas y las tuplas utilizan ahora "Py_ssize_t" para almacenar su tamaño. Funciones como "PyList_Size()" ahora devuelven "Py_ssize_t". Por lo tanto, el código de los módulos de extensión puede necesitar cambiar algunas variables a "Py_ssize_t".
The "PyArg_ParseTuple()" and "Py_BuildValue()" functions have a new conversion code, "n", for "Py_ssize_t". "PyArg_ParseTuple()"'s "s#" and "t#" still output int by default, but you can define the macro "PY_SSIZE_T_CLEAN" before including "Python.h" to make them return "Py_ssize_t".
PEP 353 tiene una sección sobre directrices de conversión que los autores de extensiones deberían leer para aprender a soportar plataformas de 64 bits.
Ver también:
PEP 353 - Uso de ssize_t como tipo de índice PEP escrito y aplicado por Martin von Löwis.
PEP 357: El método 'index'#
The NumPy developers had a problem that could only be solved by adding a new special method, "index()". When using slice notation, as in "[start:stop:step]", the values of the start, stop, and step indexes must all be either integers or long integers. NumPy defines a variety of specialized integer types corresponding to unsigned and signed integers of 8, 16, 32, and 64 bits, but there was no way to signal that these types could be used as slice indexes.
Slicing can't just use the existing "int()" method because that method is also used to implement coercion to integers. If slicing used "int()", floating-point numbers would also become legal slice indexes and that's clearly an undesirable behaviour.
Instead, a new special method called "index()" was added. It takes no arguments and returns an integer giving the slice index to use. For example:
class C: def index (self): return self.value
El valor devuelto debe ser un entero de Python o un entero largo. El intérprete comprobará que el tipo devuelto es correcto, y lanza un "TypeError" si no se cumple este requisito.
A corresponding "nb_index" slot was added to the C-level "PyNumberMethods" structure to let C extensions implement this protocol. "PyNumber_Index(obj)" can be used in extension code to call the "index()" function and retrieve its result.
Ver también:
PEP 357 - Permitir el uso de cualquier objeto para rebanar PEP escrito e implementado por Travis Oliphant.
Otros cambios lingüísticos#
Estos son todos los cambios que Python 2.5 introduce en el núcleo del lenguaje Python.
-
The "dict" type has a new hook for letting subclasses provide a default value when a key isn't contained in the dictionary. When a key isn't found, the dictionary's "missing(key)" method will be called. This hook is used to implement the new "defaultdict" class in the "collections" module. The following example defines a dictionary that returns zero for any missing key:
class zerodict (dict): def missing (self, key): return 0
d = zerodict({1:1, 2:2}) print d[1], d[2] # Prints 1, 2 print d[3], d[4] # Prints 0, 0
-
Tanto las cadenas de 8 bits como las de Unicode tienen nuevos métodos "partition(sep)" y "rpartition(sep)" que simplifican un caso de uso común.
El método "find(S)" se utiliza a menudo para obtener un índice que luego se utiliza para cortar la cadena y obtener las piezas que están antes y después del separador. El método "partition(sep)" condensa este patrón en una sola llamada al método que devuelve una tripleta que contiene la subcadena antes del separador, el propio separador y la subcadena después del separador. Si no se encuentra el separador, el primer elemento de la tupla es la cadena completa y los otros dos elementos están vacíos. "rpartition(sep)" también devuelve una tupla de 3 elementos, pero empieza a buscar desde el final de la cadena; la "r" significa "al revés".
Algunos ejemplos:
>>> ('http://www.python.org').partition('://')
('http', '://', 'www.python.org')
>>> ('file:/usr/share/doc/index.html').partition('://')
('file:/usr/share/doc/index.html', '', '')
>>> (u'Subject: a quick question').partition(':')
(u'Subject', u':', u' a quick question')
>>> 'www.python.org'.rpartition('.')
('www.python', '.', 'org')
>>> 'www.python.org'.rpartition(':')
('', '', 'www.python.org')
(Implementado por Fredrik Lundh tras una sugerencia de Raymond Hettinger)
-
The "startswith()" and "endswith()" methods of string types now accept tuples of strings to check for.
def is_image_file (nombre_archivo): return nombre_archivo.endswith(('.gif', '.jpg', '.tiff'))
(Implementado por Georg Brandl tras una sugerencia de Tom Lynn)
-
The "min()" and "max()" built-in functions gained a "key" keyword parameter analogous to the "key" argument for "sort()". This parameter supplies a function that takes a single argument and is called for every value in the list; "min()"/"max()" will return the element with the smallest/largest return value from this function. For example, to find the longest string in a list, you can do:
L = ['medium', 'longest', 'short'] # Prints 'longest' print max(L, key=len) # Prints 'short', because lexicographically 'short' has the largest value print max(L)
(Contribución de Steven Bethard y Raymond Hettinger)
-
Dos nuevas funciones incorporadas, "any()" y "all()", evalúan si un iterador contiene algún valor verdadero o falso. "any()" devuelve "True" si cualquier valor devuelto por el iterador es verdadero; en caso contrario devolverá "False". "all()" devuelve "True" sólo si todos los valores devueltos por el iterador se evalúan como verdaderos. (Sugerido por Guido van Rossum, e implementado por Raymond Hettinger)
-
The result of a class's "hash()" method can now be either a long integer or a regular integer. If a long integer is returned, the hash of that value is taken. In earlier versions the hash value was required to be a regular integer, but in 2.5 the "id()" built-in was changed to always return non-negative numbers, and users often seem to use "id(self)" in "hash()" methods (though this is discouraged).
-
ASCII es ahora la codificación por defecto para los módulos. Ahora es un error de sintaxis si un módulo contiene literales de cadena con caracteres de 8 bits pero no tiene una declaración de codificación. En Python 2.4 esto provocaba una advertencia, no un error de sintaxis. Vea en PEP 263 cómo declarar la codificación de un módulo; por ejemplo, puede añadir una línea como ésta cerca de la parte superior del fichero fuente:
#-- coding: latin1 --
-
Una nueva advertencia, "UnicodeWarning", se activa cuando se intenta comparar una cadena Unicode y una cadena de 8 bits que no se puede convertir a Unicode utilizando la codificación ASCII por defecto. El resultado de la comparación es falso:
chr(128) == unichr(128) # Can't convert chr(128) to Unicode main:1: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal False chr(127) == unichr(127) # chr(127) can be converted True
Anteriormente, esto lanzaba una excepción "UnicodeDecodeError", pero en 2.5 esto podía dar lugar a problemas desconcertantes al acceder a un diccionario. Si se buscaba "unichr(128)" y se utilizaba "chr(128)" como clave, se producía una excepción "UnicodeDecodeError". Otros cambios en la versión 2.5 hicieron que esta excepción se lanzara en lugar de ser suprimida por el código de "dictobject.c" que implementa los diccionarios.
Lanzar una excepción para tal comparación es estrictamente correcto, pero el cambio podría haber roto el código, así que en su lugar se introdujo "UnicodeWarning".
(Implementado por Marc-André Lemburg.)
-
Un error que a veces cometen los programadores de Python es olvidarse de incluir un módulo "init.py" en el directorio de un paquete. Depurar este error puede ser confuso, y normalmente requiere ejecutar Python con el modificador "-v" para registrar todas las rutas buscadas. En Python 2.5, una nueva advertencia "ImportWarning" se activa cuando una importación habría recogido un directorio como paquete pero no se encontró ningún "init.py". Esta advertencia se ignora silenciosamente por defecto; proporcione la opción "-Wd" cuando ejecute el ejecutable de Python para mostrar el mensaje de advertencia. (Implementado por Thomas Wouters)</-W>
-
La lista de clases base en una definición de clase ahora puede estar vacía. Como ejemplo, esto es ahora legal:
clase C(): pass
(Implementado por Brett Cannon.)
Cambios en el intérprete interactivo#
En el intérprete interactivo, "quit" y "exit" han sido durante mucho tiempo cadenas para que los nuevos usuarios obtengan un mensaje algo útil cuando intenten salir:
salir 'Utilice Ctrl-D (es decir, EOF) para salir.'
En Python 2.5, "quit" y "exit" son ahora objetos que siguen produciendo representaciones de cadena de sí mismos, pero también son invocables. Los novatos que prueben "quit()" o "exit()" ahora saldrán del intérprete como se espera. (Implementado por Georg Brandl.)
El ejecutable de Python ahora acepta las opciones largas estándar "-- help" y "--version"; en Windows, también acepta la opción "/?" para mostrar un mensaje de ayuda. (Implementado por Georg Brandl)
Optimizaciones#
Varias de las optimizaciones se desarrollaron en el sprint NeedForSpeed, un evento celebrado en Reikiavik, Islandia, del 21 al 28 de mayo de 2006. El sprint se centró en las mejoras de velocidad de la implementación de CPython y fue financiado por EWT LLC con el apoyo local de CCP Games. Las optimizaciones añadidas en este sprint están especialmente marcadas en la siguiente lista.
-
Cuando se introdujeron en Python 2.4, los tipos incorporados "set" y "frozenset" se construyeron sobre el tipo diccionario de Python. En 2.5 la estructura de datos interna se ha personalizado para implementar conjuntos, y como resultado los conjuntos utilizarán un tercio menos de memoria y son algo más rápidos. (Implementado por Raymond Hettinger)
-
Se ha mejorado la velocidad de algunas operaciones Unicode, como la búsqueda de subcadenas, la división de cadenas y la codificación y decodificación de mapas de caracteres. (Las mejoras en la búsqueda de subcadenas y la división fueron añadidas por Fredrik Lundh y Andrew Dalke en el sprint NeedForSpeed. Los mapas de caracteres fueron mejorados por Walter Dörwald y Martin von Löwis)
-
La función "long(str, base)" es ahora más rápida en cadenas de dígitos largos porque se calculan menos resultados intermedios. El máximo es para cadenas de alrededor de 800-1000 dígitos, donde la función es 6 veces más rápida. (Aportado por Alan McIntyre y comprometido en el sprint NeedForSpeed)
-
It's now illegal to mix iterating over a file with "for line in file" and calling the file object's "read()"/"readline()"/"readlines()" methods. Iteration uses an internal buffer and the "read()" methods don't use that buffer. Instead they would return the data following the buffer, causing the data to appear out of order. Mixing iteration and these methods will now trigger a "ValueError" from the "read()" method. (Implemented by Thomas Wouters.)
-
El módulo "struct" ahora compila cadenas de formato de estructura en una representación interna y almacena en caché esta representación, lo que supone una mejora del 20% s. (Contribuido por Bob Ippolito en el sprint NeedForSpeed)
-
El módulo "re" obtuvo un 1 o 2% s de velocidad al cambiar a las funciones asignadoras de Python en lugar de las "malloc()" y "free()" del sistema. (Contribuido por Jack Diederich en el sprint NeedForSpeed)
-
El optimizador de la mirilla del generador de código realiza ahora un simple plegado de constantes en las expresiones. Si escribes algo como "a = 2+3", el generador de código hará la aritmética y producirá el código correspondiente a "a = 5". (Propuesto e implementado por Raymond Hettinger)
-
Las llamadas a funciones son ahora más rápidas porque los objetos de código guardan ahora el último fotograma terminado (un "fotograma zombi") en un campo interno del objeto de código, reutilizándolo la próxima vez que se invoque el objeto de código. (Parche original de Michael Hudson, modificado por Armin Rigo y Richard Jones; confirmado en el sprint NeedForSpeed) Los objetos marco son también ligeramente más pequeños, lo que puede mejorar la localidad de la caché y reducir un poco el uso de la memoria. (Contribución de Neal Norwitz)
-
Las excepciones incorporadas en Python son ahora clases de nuevo estilo, un cambio que acelera considerablemente la instanciación. El manejo de excepciones en Python 2.5 es, por tanto, un 30% f más rápido que en 2.4. (Contribución de Richard Jones, Georg Brandl y Sean Reifschneider en el sprint NeedForSpeed)
-
Importing now caches the paths tried, recording whether they exist or not so that the interpreter makes fewer "open()" and "stat()" calls on startup. (Contributed by Martin von Löwis and Georg Brandl.)
Módulos nuevos, mejorados y eliminados#
La biblioteca estándar ha recibido muchas mejoras y correcciones de errores en Python 2.5. Aquí hay una lista parcial de los cambios más notables, ordenados alfabéticamente por el nombre del módulo. Consulte el archivo "Misc/NEWS" en el árbol de fuentes para obtener una lista más completa de los cambios, o busque en los registros de SVN para obtener todos los detalles.
-
El módulo "audioop" ahora admite la codificación a-LAW y se ha mejorado el código para la codificación u-LAW. (Contribución de Lars Immisch).
-
The "codecs" module gained support for incremental codecs. The "codecs.lookup()" function now returns a "CodecInfo" instance instead of a tuple. "CodecInfo" instances behave like a 4-tuple to preserve backward compatibility but also have the attributes "encode", "decode", "incrementalencoder", "incrementaldecoder", "streamwriter", and "streamreader". Incremental codecs can receive input and produce output in multiple chunks; the output is the same as if the entire input was fed to the non-incremental codec. See the "codecs" module documentation for details. (Designed and implemented by Walter Dörwald.)
-
The "collections" module gained a new type, "defaultdict", that subclasses the standard "dict" type. The new type mostly behaves like a dictionary but constructs a default value when a key isn't present, automatically adding it to the dictionary for the requested key value.
The first argument to "defaultdict"'s constructor is a factory function that gets called whenever a key is requested but not found. This factory function receives no arguments, so you can use built-in type constructors such as "list()" or "int()". For example, you can make an index of words based on their initial letter like this:
palabras = """Nel mezzo del cammin di nuestra vita
mi ritrovai per una selva oscura
che la diritta via era smarrita""".lower().split()
índice = dictamen predeterminado (lista)
para w en palabras:
letra_inicial = w[0]
índice[letra_inicio].append(w)
Al imprimir "index" se obtiene la siguiente salida:
defaultdict(<type 'list'>, {'c': ['cammin', 'che'], 'e': ['era'],
'd': ['del', 'di', 'diritta'], 'm': ['mezzo', 'mi'],
'l': ['la'], 'o': ['oscura'], 'n': ['nel', 'nostra'],
'p': ['per'], 's': ['selva', 'smarrita'],
'r': ['ritrovai'], 'u': ['una'], 'v': ['vita', 'via']}
(Contribución de Guido van Rossum.)
-
The "deque" double-ended queue type supplied by the "collections" module now has a "remove(value)" method that removes the first occurrence of value in the queue, raising "ValueError" if the value isn't found. (Contributed by Raymond Hettinger.)
-
Nuevo módulo: El módulo "contextlib" contiene funciones de ayuda para usar con la nueva sentencia '"with"'. Consulte la sección El módulo contextlib para obtener más información sobre este módulo.
-
Nuevo módulo: El módulo "cProfile" es una implementación en C del módulo existente "profile" que tiene una sobrecarga mucho menor. La interfaz del módulo es la misma que la de "profile": se ejecuta "cProfile.run('main()')" para perfilar una función, se pueden guardar los datos del perfil en un archivo, etc. Todavía no se sabe si el perfilador Hotshot, que también está escrito en C pero no coincide con la interfaz del módulo "profile", seguirá manteniéndose en futuras versiones de Python. (Contribución de Armin Rigo.)
Also, the "pstats" module for analyzing the data measured by the profiler now supports directing the output to any file object by supplying a stream argument to the "Stats" constructor. (Contributed by Skip Montanaro.)
- The "csv" module, which parses files in comma-separated value format, received several enhancements and a number of bugfixes. You can now set the maximum size in bytes of a field by calling the "csv.field_size_limit(new_limit)" function; omitting the new_limit argument will return the currently set limit. The "reader" class now has a "line_num" attribute that counts the number of physical lines read from the source; records can span multiple physical lines, so "line_num" is not the same as the number of records read.
El analizador CSV es ahora más estricto con los campos entrecomillados de varias líneas. Anteriormente, si una línea terminaba dentro de un campo entre comillas sin un carácter de nueva línea final, se insertaba una nueva línea en el campo devuelto. Este comportamiento causaba problemas cuando se leían archivos que contenían caracteres de retorno de carro dentro de los campos, por lo que se cambió el código para devolver el campo sin insertar nuevas líneas. Como consecuencia, si las nuevas líneas incrustadas dentro de los campos son importantes, la entrada debe dividirse en líneas de manera que se conserven los caracteres de nueva línea.
(Contribución de Skip Montanaro y Andrew McNamara)
-
La clase "datetime" del módulo "datetime" tiene ahora un método "strptime(string, format)" para analizar cadenas de fechas, aportado por Josh Spoerri. Utiliza los mismos caracteres de formato que "time.strptime()" y "time.strftime()":
import datetime as dt
ts = dt.datetime.strptime('10:13:15 2006-03-07', '%H:%M:%S %Y-%m-%d')
-
The "difflib.SequenceMatcher.get_matching_blocks()" method in the "difflib" module now guarantees to return a minimal list of blocks describing matching subsequences. Previously, the algorithm would occasionally break a block of matching elements into two list entries. (Enhancement by Tim Peters.)
-
El módulo "doctest" ha ganado una opción "SKIP" que impide que un ejemplo se ejecute en absoluto. Esto está pensado para los fragmentos de código que son ejemplos de uso destinados al lector y que no son realmente casos de prueba.
An encoding parameter was added to the "testfile()" function and the "DocFileSuite" class to specify the file's encoding. This makes it easier to use non-ASCII characters in tests contained within a docstring. (Contributed by Bjorn Tillenius.)
-
El paquete "email" ha sido actualizado a la versión 4.0. (Contribución de Barry Warsaw.)
-
The "fileinput" module was made more flexible. Unicode filenames are now supported, and a mode parameter that defaults to ""r"" was added to the "input()" function to allow opening files in binary or universal newlines mode. Another new parameter, openhook, lets you use a function other than "open()" to open the input files. Once you're iterating over the set of files, the "FileInput" object's new "fileno()" returns the file descriptor for the currently opened file. (Contributed by Georg Brandl.)
-
In the "gc" module, the new "get_count()" function returns a 3-tuple containing the current collection counts for the three GC generations. This is accounting information for the garbage collector; when these counts reach a specified threshold, a garbage collection sweep will be made. The existing "gc.collect()" function now takes an optional generation argument of 0, 1, or 2 to specify which generation to collect. (Contributed by Barry Warsaw.)
-
The "nsmallest()" and "nlargest()" functions in the "heapq" module now support a "key" keyword parameter similar to the one provided by the "min()"/"max()" functions and the "sort()" methods. For example:
import heapq L = ["short", 'medium', 'longest', 'longer still'] heapq.nsmallest(2, L) # Return two lowest elements, lexicographically ['longer still', 'longest'] heapq.nsmallest(2, L, key=len) # Return two shortest elements ['short', 'medium']
(Contribución de Raymond Hettinger.)
-
La función "itertools.islice()" ahora acepta "None" para los argumentos de inicio y paso. Esto la hace más compatible con los atributos de los objetos slice, por lo que ahora se puede escribir lo siguiente:
s = slice(5) # Crear objeto slice itertools.islice(iterable, s.start, s.stop, s.step)
(Contribución de Raymond Hettinger.)
- The "format()" function in the "locale" module has been modified and two new functions were added, "format_string()" and "currency()".
El parámetro val de la función "format()" podía ser antes una cadena siempre que no apareciera más de un especificador %char; ahora el parámetro debe ser exactamente un especificador %char sin texto alrededor. También se ha añadido un parámetro opcional monetario que, si es "Verdadero", utilizará las reglas de la configuración regional para formatear la moneda al colocar un separador entre grupos de tres dígitos.
To format strings with multiple %char specifiers, use the new "format_string()" function that works like "format()" but also supports mixing %char specifiers with arbitrary text.
A new "currency()" function was also added that formats a number according to the current locale's settings.
(Contribución de Georg Brandl.)
-
The "mailbox" module underwent a massive rewrite to add the capability to modify mailboxes in addition to reading them. A new set of classes that include "mbox", "MH", and "Maildir" are used to read mailboxes, and have an "add(message)" method to add messages, "remove(key)" to remove messages, and "lock()"/"unlock()" to lock/unlock the mailbox. The following example converts a maildir- format mailbox into an mbox-format one:
importar buzón
# 'factory=None' utiliza email.Message.Message como la clase que representa # los mensajes individuales. src = mailbox.Maildir('maildir', factory=None) dest = mailbox.mbox('/tmp/mbox')
para msg en src: dest.add(msg)
(Contribución de Gregory K. Johnson. La financiación fue proporcionada por el Summer of Code 2005 de Google)
-
Nuevo módulo: el módulo "msilib" permite crear archivos ".msi" y archivos CAB de Microsoft Installer. También se incluye cierta compatibilidad para leer la base de datos ".msi". (Contribución de Martin von Löwis).
-
El módulo "nis" ahora permite acceder a dominios distintos del dominio predeterminado del sistema mediante el suministro de un argumento domain a las funciones "nis.match()" y "nis.maps()". (Contribuido por Ben Bell).
-
The "operator" module's "itemgetter()" and "attrgetter()" functions now support multiple fields. A call such as "operator.attrgetter('a', 'b')" will return a function that retrieves the "a" and "b" attributes. Combining this new feature with the "sort()" method's "key" parameter lets you easily sort lists using multiple fields. (Contributed by Raymond Hettinger.)
-
The "optparse" module was updated to version 1.5.1 of the Optik library. The "OptionParser" class gained an "epilog" attribute, a string that will be printed after the help message, and a "destroy()" method to break reference cycles created by the object. (Contributed by Greg Ward.)
-
The "os" module underwent several changes. The "stat_float_times" variable now defaults to true, meaning that "os.stat()" will now return time values as floats. (This doesn't necessarily mean that "os.stat()" will return times that are precise to fractions of a second; not all systems support such precision.)
Se han añadido las constantes "os.SEEK_SET", "os.SEEK_CUR" y "os.SEEK_END", que son los parámetros de la función "os.lseek()". Dos nuevas constantes para el bloqueo son "os.O_SHLOCK" y "os.O_EXLOCK".
Two new functions, "wait3()" and "wait4()", were added. They're similar the "waitpid()" function which waits for a child process to exit and returns a tuple of the process ID and its exit status, but "wait3()" and "wait4()" return additional information. "wait3()" doesn't take a process ID as input, so it waits for any child process to exit and returns a 3-tuple of process-id, exit- status, resource-usage as returned from the "resource.getrusage()" function. "wait4(pid)" does take a process ID. (Contributed by Chad J. Schroeder.)
On FreeBSD, the "os.stat()" function now returns times with nanosecond resolution, and the returned object now has "st_gen" and "st_birthtime". The "st_flags" attribute is also available, if the platform supports it. (Contributed by Antti Louko and Diego Pettenò.)
-
El depurador de Python proporcionado por el módulo "pdb" puede ahora almacenar listas de comandos a ejecutar cuando se alcanza un punto de ruptura y se detiene la ejecución. Una vez creado el punto de interrupción nº 1, introduzca "comandos 1" e introduzca una serie de comandos a ejecutar, terminando la lista con "end". La lista de comandos puede incluir comandos que reanuden la ejecución, como "continue" o "next". (Contribución de Grégoire Dooms.)
-
Los módulos "pickle" y "cPickle" ya no aceptan un valor de retorno de "None" del método "reduce()"; en su lugar, el método debe devolver una tupla de argumentos. La capacidad de devolver "None" quedó obsoleta en Python 2.4, por lo que esto completa la eliminación de la función.
-
El módulo "pkgutil", que contiene varias funciones de utilidad para encontrar paquetes, fue mejorado para soportar los ganchos de importación de PEP 302 y ahora también funciona para paquetes almacenados en archivos con formato ZIP. (Contribución de Phillip J. Eby)
-
El conjunto de pruebas pybench de Marc-André Lemburg se incluye ahora en el directorio "Tools/pybench". El conjunto de pruebas pybench es una mejora del programa "pystone.py" de uso común, ya que pybench proporciona una medición más detallada de la velocidad del intérprete. Calcula el tiempo de determinadas operaciones como las llamadas a funciones, el corte de tuplas, las búsquedas de métodos y las operaciones numéricas, en lugar de realizar muchas operaciones diferentes y reducir el resultado a un único número como hace "pystone.py".
-
The "pyexpat" module now uses version 2.0 of the Expat parser. (Contributed by Trent Mick.)
-
The "Queue" class provided by the "queue" module gained two new methods. "join()" blocks until all items in the queue have been retrieved and all processing work on the items have been completed. Worker threads call the other new method, "task_done()", to signal that processing for an item has been completed. (Contributed by Raymond Hettinger.)
-
The old "regex" and "regsub" modules, which have been deprecated ever since Python 2.0, have finally been deleted. Other deleted modules: "statcache", "tzparse", "whrandom".
-
Also deleted: the "lib-old" directory, which includes ancient modules such as "dircmp" and "ni", was removed. "lib-old" wasn't on the default "sys.path", so unless your programs explicitly added the directory to "sys.path", this removal shouldn't affect your code.
-
El módulo "rlcompleter" ya no depende de la importación del módulo "readline" y, por lo tanto, ahora funciona en plataformas no Unix. (Parche de Robert Kiendl.)
-
The "SimpleXMLRPCServer" and "DocXMLRPCServer" classes now have a "rpc_paths" attribute that constrains XML-RPC operations to a limited set of URL paths; the default is to allow only "'/'" and "'/RPC2'". Setting "rpc_paths" to "None" or an empty tuple disables this path checking.
-
The "socket" module now supports "AF_NETLINK" sockets on Linux, thanks to a patch from Philippe Biondi. Netlink sockets are a Linux-specific mechanism for communications between a user-space process and kernel code; an introductory article about them is at https://www.linuxjournal.com/article/7356. In Python code, netlink addresses are represented as a tuple of 2 integers, "(pid, group_mask)".
Dos nuevos métodos en objetos socket, "recv_into(buffer)" y "recvrom_into(buffer)", almacenan los datos recibidos en un objeto que soporta el protocolo de buffer en lugar de devolver los datos como una cadena. Esto significa que puedes poner los datos directamente en un array o en un archivo mapeado en memoria.
Socket objects also gained "getfamily()", "gettype()", and "getproto()" accessor methods to retrieve the family, type, and protocol values for the socket.
-
Nuevo módulo: el módulo "spwd" proporciona funciones para acceder a la base de datos de contraseñas ocultas en sistemas que admiten contraseñas ocultas.
-
The "struct" is now faster because it compiles format strings into "Struct" objects with "pack()" and "unpack()" methods. This is similar to how the "re" module lets you create compiled regular expression objects. You can still use the module-level "pack()" and "unpack()" functions; they'll create "Struct" objects and cache them. Or you can use "Struct" instances directly:
s = struct.Struct('ih3s')
data = s.pack(1972, 187, 'abc') year, number, name = s.unpack(data)
También puedes empaquetar y desempaquetar datos hacia y desde objetos buffer directamente usando los métodos "pack_into(buffer, offset, v1, v2, ...)" y "unpack_from(buffer, offset)". Esto te permite almacenar datos directamente en un array o en un archivo mapeado en memoria.
("Struct" objects were implemented by Bob Ippolito at the NeedForSpeed sprint. Support for buffer objects was added by Martin Blais, also at the NeedForSpeed sprint.)
- Los desarrolladores de Python cambiaron de CVS a Subversion durante el proceso de desarrollo de la versión 2.5. La información sobre la versión exacta de construcción está disponible como la variable "sys.subversion", una 3-tupla de "(nombre del intérprete, nombre de la rama, rango de revisión)". Por ejemplo, en el momento de escribir esto, mi copia de 2.5 informaba de "('CPython', 'trunk', '45313:45315')".
Esta información también está disponible para las extensiones de C a través de la función "Py_GetBuildInfo()" que devuelve una cadena de información de compilación como esta ""trunk:45355:45356M, Apr 13 2006, 07:42:19"". (Contribuido por Barry Warsaw.)
-
Otra nueva función, "sys._current_frames()", devuelve los marcos de pila actuales para todos los hilos en ejecución como un diccionario que asigna los identificadores de los hilos al marco de pila superior actualmente activo en ese hilo en el momento en que se llama a la función. (Contribuido por Tim Peters.)
-
The "TarFile" class in the "tarfile" module now has an "extractall()" method that extracts all members from the archive into the current working directory. It's also possible to set a different directory as the extraction target, and to unpack only a subset of the archive's members.
La compresión utilizada para un archivo tar abierto en modo stream puede ahora ser autodetectada utilizando el modo "'r|*'". (Contribución de Lars Gustäbel)
-
El módulo "threading" permite ahora establecer el tamaño de la pila utilizado cuando se crean nuevos hilos. La función "stack_size([size])" devuelve el tamaño de pila actualmente configurado, y suministrando el parámetro opcional size establece un nuevo valor. No todas las plataformas soportan el cambio del tamaño de la pila, pero Windows, POSIX threading y OS/2 lo hacen. (Contribución de Andrew MacIntyre)
-
El módulo "unicodedata" ha sido actualizado para utilizar la versión 4.1.0 de la base de datos de caracteres Unicode. La versión 3.2.0 es requerida por algunas especificaciones, por lo que sigue estando disponible como "unicodedata.ucd_3_2_0".
-
New module: the "uuid" module generates universally unique identifiers (UUIDs) according to RFC 4122. The RFC defines several different UUID versions that are generated from a starting string, from system properties, or purely randomly. This module contains a "UUID" class and functions named "uuid1()", "uuid3()", "uuid4()", and "uuid5()" to generate different versions of UUID. (Version 2 UUIDs are not specified in RFC 4122 and are not supported by this module.)
import uuid
make a UUID based on the host ID and current time#
uuid.uuid1() UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
make a UUID using an MD5 hash of a namespace UUID and a name#
uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org') UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')
make a random UUID#
uuid.uuid4() UUID('16fd2706-8baf-433b-82eb-8c7fada847da')
make a UUID using a SHA-1 hash of a namespace UUID and a name#
uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org') UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
(Contribución de Ka-Ping Yee.)
-
The "weakref" module's "WeakKeyDictionary" and "WeakValueDictionary" types gained new methods for iterating over the weak references contained in the dictionary. "iterkeyrefs()" and "keyrefs()" methods were added to "WeakKeyDictionary", and "itervaluerefs()" and "valuerefs()" were added to "WeakValueDictionary". (Contributed by Fred L. Drake, Jr.)
-
The "webbrowser" module received a number of enhancements. It's now usable as a script with "python -m webbrowser", taking a URL as the argument; there are a number of switches to control the behaviour ("-n" for a new browser window, "-t" for a new tab). New module- level functions, "open_new()" and "open_new_tab()", were added to support this. The module's "open()" function supports an additional feature, an autoraise parameter that signals whether to raise the open window when possible. A number of additional browsers were added to the supported list such as Firefox, Opera, Konqueror, and elinks. (Contributed by Oleg Broytmann and Georg Brandl.)
-
El módulo "xmlrpclib" ahora admite la devolución de objetos "datetime" para el tipo de fecha XML-RPC. Proporcione "use_datetime=True" a la función "loads()" o a la clase "Unmarshaller" para habilitar esta función. (Contribuido por Skip Montanaro).
-
El módulo "zipfile" ahora soporta la versión ZIP64 del formato, lo que significa que un archivo .zip ahora puede ser mayor de 4 GiB y puede contener archivos individuales mayores de 4 GiB. (Contribución de Ronald Oussoren)
-
The "zlib" module's "Compress" and "Decompress" objects now support a "copy()" method that makes a copy of the object's internal state and returns a new "Compress" or "Decompress" object. (Contributed by Chris AtLee.)
El paquete ctypes#
El paquete "ctypes", escrito por Thomas Heller, se ha añadido a la biblioteca estándar. "ctypes" permite llamar a funciones arbitrarias en bibliotecas compartidas o DLL. Los usuarios habituales pueden recordar el módulo "dl", que proporciona funciones para cargar bibliotecas compartidas y llamar a funciones en ellas. El paquete "ctypes" es mucho más sofisticado.
To load a shared library or DLL, you must create an instance of the "CDLL" class and provide the name or path of the shared library or DLL. Once that's done, you can call arbitrary functions by accessing them as attributes of the "CDLL" object.
import ctypes
libc = ctypes.CDLL('libc.so.6') result = libc.printf("Line of output\n")
Type constructors for the various C types are provided: "c_int()", "c_float()", "c_double()", "c_char_p()" (equivalent to char), and so forth. Unlike Python's types, the C versions are all mutable; you can assign to their "value" attribute to change the wrapped value. Python integers and strings will be automatically converted to the corresponding C types, but for other types you must call the correct type constructor. (And I mean must*; getting it wrong will often result in the interpreter crashing with a segmentation fault.)
You shouldn't use "c_char_p()" with a Python string when the C function will be modifying the memory area, because Python strings are supposed to be immutable; breaking this rule will cause puzzling bugs. When you need a modifiable memory area, use "create_string_buffer()":
s = "this is a string" buf = ctypes.create_string_buffer(s) libc.strfry(buf)
C functions are assumed to return integers, but you can set the "restype" attribute of the function object to change this:
libc.atof('2.71828') -1783957616 libc.atof.restype = ctypes.c_double libc.atof('2.71828') 2.71828
"ctypes" también proporciona un contenedor para la API C de Python como el objeto "ctypes.pythonapi". Este objeto libera el bloqueo global del intérprete antes de llamar a una función, porque el bloqueo debe mantenerse al llamar al código del intérprete. Hay un constructor de tipo "py_object" que creará un puntero PyObject*. Un uso simple:
import ctypes
d = {} ctypes.pythonapi.PyObject_SetItem(ctypes.py_object(d), ctypes.py_object("abc"), ctypes.py_object(1)) # d is now {'abc', 1}.
No olvide utilizar "py_object()"; si lo omite, terminará con un error de segmentación.
"ctypes" existe desde hace tiempo, pero la gente sigue escribiendo y distribuyendo módulos de extensión codificados a mano porque no se puede confiar en que "ctypes" esté presente. Quizás los desarrolladores empiecen a escribir envoltorios de Python sobre una biblioteca a la que se accede a través de "ctypes" en lugar de módulos de extensión, ahora que "ctypes" está incluido en el núcleo de Python.
Ver también:
https://web.archive.org/web/20180410025338/http://starship.python.n et/crew/theller/ctypes/ La página web pre-stdlib ctypes, con un tutorial, referencia y preguntas frecuentes.
La documentación del módulo "ctypes".
El paquete ElementTree#
A subset of Fredrik Lundh's ElementTree library for processing XML has been added to the standard library as "xml.etree". The available modules are "ElementTree", "ElementPath", and "ElementInclude" from ElementTree 1.2.6. The "cElementTree" accelerator module is also included.
El resto de esta sección proporcionará una breve descripción general del uso de ElementTree. La documentación completa de ElementTree está disponible en https://web.archive.org/web/20201124024954/http://effbot.org/zone /element-index.htm.
ElementTree represents an XML document as a tree of element nodes. The text content of the document is stored as the "text" and "tail" attributes of (This is one of the major differences between ElementTree and the Document Object Model; in the DOM there are many different types of node, including "TextNode".)
The most commonly used parsing function is "parse()", that takes either a string (assumed to contain a filename) or a file-like object and returns an "ElementTree" instance:
from xml.etree import ElementTree as ET
tree = ET.parse('ex-1.xml')
feed = urllib.urlopen( 'http://planet.python.org/rss10.xml') tree = ET.parse(feed)
Once you have an "ElementTree" instance, you can call its "getroot()" method to get the root "Element" node.
There's also an "XML()" function that takes a string literal and returns an "Element" node (not an "ElementTree"). This function provides a tidy way to incorporate XML fragments, approaching the convenience of an XML literal:
svg = ET.XML("""""") svg.set('height', '320px') svg.append(elem1)
Cada elemento XML admite algunos métodos de acceso tipo diccionario y otros tipo lista. Las operaciones tipo diccionario se utilizan para acceder a los valores de los atributos, y las operaciones tipo lista se utilizan para acceder a los nodos hijos.
+---------------------------------+----------------------------------------------+ | Operación | Resultado | |=================================|==============================================|
| "elem[n]" | Devuelve el elemento hijo enésimo. |#
| "elem[m:n]" | Devuelve la lista de m's a n's elementos |
| | hijos. |#
| "len(elem)" | Devuelve el número de elementos hijos. |#
| "lista(elem)" | Devuelve la lista de elementos hijos. |#
| "elem.append(elem2)" | Añade elemento2 como hijo. |#
| "elem.insert(index, elem2)" | Inserta elemento2 en el lugar |
| | especificado. |#
| "del elem[n]" | Elimina el elemento hijo enésimo. |#
| "elem.keys()" | Devuelve la lista de nombres de atributos. |#
| "elem.get(name)" | Devuelve el valor del atributo nombre. |#
| "elem.set(nombre, valor)" | Establece el nuevo valor del atributo |
| | nombre. |#
| "elem.attrib" | Recupera el diccionario que contiene los |
| | atributos. |#
| "del elem.attrib[name]" | Borra el atributo nombre. |#
Comments and processing instructions are also represented as "Element" nodes. To check if a node is a comment or processing instructions:
if elem.tag is ET.Comment: ... elif elem.tag is ET.ProcessingInstruction: ...
To generate XML output, you should call the "xml.etree.ElementTree.ElementTree.write()" method. Like "parse()", it can take either a string or a file-like object:
# Encoding is US-ASCII tree.write('output.xml')
# Encoding is UTF-8 f = open('output.xml', 'w') tree.write(f, encoding='utf-8')
(Atención: la codificación por defecto utilizada para la salida es ASCII. Para el trabajo general de XML, donde el nombre de un elemento puede contener caracteres Unicode arbitrarios, ASCII no es una codificación muy útil porque lanzará una excepción si el nombre de un elemento contiene cualquier carácter con valores superiores a 127. Por lo tanto, es mejor especificar una codificación diferente, como UTF-8, que puede manejar cualquier carácter Unicode)
Esta sección es sólo una descripción parcial de las interfaces de ElementTree. Por favor, lee la documentación oficial del paquete para más detalles.
Ver también:
https://web.archive.org/web/20201124024954/http://effbot.org/zone /element-index.htm Documentación oficial de ElementTree.
El paquete hashlib#
Se ha añadido un nuevo módulo "hashlib", escrito por Gregory P. Smith, para sustituir a los módulos "md5" y "sha". "hashlib" añade compatibilidad con hashes seguros adicionales (SHA-224, SHA-256, SHA-384 y SHA-512). Cuando está disponible, el módulo utiliza OpenSSL para implementaciones rápidas y optimizadas de algoritmos para plataformas.
Los módulos antiguos "md5" y "sha" todavía existen como contenedores de hashlib para preservar la compatibilidad con versiones anteriores. La interfaz del nuevo módulo es muy similar a la de los módulos antiguos, pero no idéntica. La diferencia más significativa es que las funciones constructoras para crear nuevos objetos hash tienen nombres diferentes.
# Versiones anteriores h = md5.md5() h = md5.new()
# Nueva versión h = hashlib.md5()
# Versiones anteriores h = sha.sha() h = sha.new()
# Nueva versión h = hashlib.sha1()
# Hash que no estaban disponibles anteriormente h = hashlib.sha224() h = hashlib.sha256() h = hashlib.sha384() h = hashlib.sha512()
# Forma alternativa h = hashlib.new('md5') # Proporcionar algoritmo como cadena
Once a hash object has been created, its methods are the same as before: "update(string)" hashes the specified string into the current digest state, "digest()" and "hexdigest()" return the digest value as a binary string or a string of hex digits, and "copy()" returns a new hashing object with the same digest state.
Ver también: La documentación del módulo "hashlib".
El paquete sqlite3#
El módulo pysqlite (https://www.pysqlite.org), un envoltorio para la base de datos incrustada de SQLite, se agregó a la biblioteca estándar con el nombre de paquete "sqlite3".
SQLite es una biblioteca en C que proporciona una base de datos ligera basada en disco que no requiere un proceso de servidor independiente y permite acceder a la base de datos utilizando una variante no estándar del lenguaje de consulta SQL. Algunas aplicaciones pueden utilizar SQLite para el almacenamiento interno de datos. También es posible crear un prototipo de una aplicación utilizando SQLite y luego portar el código a una base de datos más grande como PostgreSQL u Oracle.
pysqlite fue escrito por Gerhard Häring y proporciona una interfaz SQL que cumple con la especificación DB-API 2.0 descrita por PEP 249.
Si estás compilando el código fuente de Python tú mismo, ten en cuenta que el árbol de código fuente no incluye el código de SQLite, sólo el módulo envolvente. Necesitarás tener las librerías y cabeceras de SQLite instaladas antes de compilar Python, y el proceso de construcción compilará el módulo cuando las cabeceras necesarias estén disponibles.
To use the module, you must first create a "Connection" object that represents the database. Here the data will be stored in the "/tmp/example" file:
conn = sqlite3.connect('/tmp/ejemplo')
También puede suministrar el nombre especial ":memory:" para crear una base de datos en la RAM.
Once you have a "Connection", you can create a "Cursor" object and call its "execute()" method to perform SQL commands:
c = conn.cursor()
# Create table c.execute('''create table stocks (date text, trans text, symbol text, qty real, price real)''')
# Insert a row of data c.execute("""insert into stocks values ('2006-01-05','BUY','RHAT',100,35.14)""")
Normalmente tus operaciones SQL necesitarán usar valores de variables de Python. No deberías montar tu consulta usando las operaciones de cadena de Python porque hacerlo es inseguro; hace que tu programa sea vulnerable a un ataque de inyección SQL.
Instead, use the DB-API's parameter substitution. Put "?" as a placeholder wherever you want to use a value, and then provide a tuple of values as the second argument to the cursor's "execute()" method. (Other database modules may use a different placeholder, such as "%s" or ":1".) For example:
# Never do this -- insecure! symbol = 'IBM' c.execute("... where symbol = '%s'" % symbol)
# Do this instead t = (symbol,) c.execute('select * from stocks where symbol=?', t)
# Larger example for t in (('2006-03-28', 'BUY', 'IBM', 1000, 45.00), ('2006-04-05', 'BUY', 'MSOFT', 1000, 72.00), ('2006-04-06', 'SELL', 'IBM', 500, 53.00), ): c.execute('insert into stocks values (?,?,?,?,?)', t)
To retrieve data after executing a SELECT statement, you can either treat the cursor as an iterator, call the cursor's "fetchone()" method to retrieve a single matching row, or call "fetchall()" to get a list of the matching rows.
Este ejemplo utiliza la forma del iterador:
c = conn.cursor() c.execute('select * from stocks order by price') for row in c: ... print row ... (u'2006-01-05', u'BUY', u'RHAT', 100, 35.140000000000001) (u'2006-03-28', u'BUY', u'IBM', 1000, 45.0) (u'2006-04-06', u'SELL', u'IBM', 500, 53.0) (u'2006-04-05', u'BUY', u'MSOFT', 1000, 72.0)
Para más información sobre el dialecto SQL soportado por SQLite, consulte https://www.sqlite.org.
Ver también:
https://www.pysqlite.org La página web de pysqlite.
https://www.sqlite.org La página web de SQLite; la documentación describe la sintaxis y los tipos de datos disponibles para el dialecto SQL soportado.
La documentación del módulo "sqlite3".
PEP 249 - Especificación de la API de la base de datos 2.0 PEP escrito por Marc-André Lemburg.
El paquete wsgiref#
La Interfaz de Pasarela del Servidor Web (WSGI) v1.0 define una interfaz estándar entre los servidores web y las aplicaciones web de Python y se describe en PEP 333. El paquete "wsgiref" es una implementación de referencia de la especificación WSGI.
El paquete incluye un servidor HTTP básico que ejecutará una aplicación WSGI; este servidor es útil para la depuración pero no está pensado para su uso en producción. La configuración de un servidor sólo requiere unas pocas líneas de código:
from wsgiref import simple_server
wsgi_app = ...
host = '' port = 8000 httpd = simple_server.make_server(host, port, wsgi_app) httpd.serve_forever()
Ver también:
https://web.archive.org/web/20160331090247/http://wsgi.readthedocs. org/en/latest/ Un sitio web central para los recursos relacionados con WSGI.
PEP 333 - Interfaz del servidor web Python v1.0 PEP escrito por Phillip J. Eby.
Cambios en la API de construcción y C#
Los cambios en el proceso de construcción de Python y en la API de C incluyen:
-
El árbol de fuentes de Python fue convertido de CVS a Subversion, en un complejo procedimiento de migración que fue supervisado y llevado a cabo de forma impecable por Martin von Löwis. El procedimiento se desarrolló como PEP 347.
-
Coverity, una empresa que comercializa una herramienta de análisis de código fuente llamada Prevent, proporcionó los resultados de su examen del código fuente de Python. El análisis encontró alrededor de 60 errores que fueron rápidamente corregidos. Muchos de los errores eran problemas de recuento, que a menudo se producen en el código de gestión de errores. Consulte las estadísticas en https://scan.coverity.com.
-
El mayor cambio en la API de C provino de PEP 353, que modifica el intérprete para usar una definición de tipo "Py_ssize_t" en lugar de int. Consulte la sección anterior PEP 353: Uso de ssize_t como tipo de índice para obtener una explicación de este cambio.
-
El diseño del compilador de código de bytes ha cambiado mucho, ya no genera código de bytes recorriendo el árbol de análisis sintáctico. En su lugar, el árbol de análisis se convierte en un árbol de sintaxis abstracta (o AST), y es el árbol de sintaxis abstracta el que se recorre para producir el código de bytes.
Es posible que el código Python obtenga objetos AST utilizando el built-in "compile()" y especificando "_ast.PyCF_ONLY_AST" como valor del parámetro flags:
from _ast import PyCF_ONLY_AST
ast = compile("""a=0
for i in range(10):
a += i
""", "<string>", 'exec', PyCF_ONLY_AST)
assignment = ast.body[0]
for_loop = ast.body[1]
No official documentation has been written for the AST code yet, but PEP 339 discusses the design. To start learning about the code, read the definition of the various AST nodes in "Parser/Python.asdl". A Python script reads this file and generates a set of C structure definitions in "Include/Python-ast.h". The "PyParser_ASTFromString()" and "PyParser_ASTFromFile()", defined in "Include/pythonrun.h", take Python source as input and return the root of an AST representing the contents. This AST can then be turned into a code object by "PyAST_Compile()". For more information, read the source code, and then ask questions on python- dev.
El código de la AST fue desarrollado bajo la dirección de Jeremy Hylton, e implementado por (en orden alfabético) Brett Cannon, Nick Coghlan, Grant Edwards, John Ehresman, Kurt Kaiser, Neal Norwitz, Tim Peters, Armin Rigo y Neil Schemenauer, además de los participantes en varios sprints de la AST en conferencias como la PyCon.
- Se aplicó el parche de Evan Jones a obmalloc, descrito por primera vez en una charla en la PyCon DC 2005. Python 2.4 asignaba objetos pequeños en arenas de 256K, pero nunca liberaba arenas. Con este parche, Python liberará arenas cuando estén vacías. El efecto neto es que en algunas plataformas, cuando se asignan muchos objetos, el uso de la memoria de Python puede realmente caer cuando se borran y la memoria puede ser devuelta al sistema operativo. (Implementado por Evan Jones, y reelaborado por Tim Peters)
Tenga en cuenta que este cambio significa que los módulos de extensión deben ser más cuidadosos al asignar memoria. La API de Python tiene muchas funciones diferentes para asignar memoria que se agrupan en familias. Por ejemplo, "PyMem_Malloc()", "PyMem_Realloc()", y "PyMem_Free()" son una familia que asigna memoria en bruto, mientras que "PyObject_Malloc()", "PyObject_Realloc()", y "PyObject_Free()" son otra familia que se supone que se utiliza para crear objetos de Python.
Anteriormente estas diferentes familias se reducían a las funciones "malloc()" y "free()" de la plataforma. Esto significaba que no importaba si te equivocabas y asignabas memoria con la función "PyMem" pero la liberabas con la función "PyObject". Con los cambios de la versión 2.5 en obmalloc, estas familias hacen ahora cosas diferentes y los desajustes probablemente darán lugar a un fallo de seguridad. Deberías probar cuidadosamente tus módulos de extensión C con Python 2.5.
-
Los tipos de conjuntos incorporados tienen ahora una API oficial en C. Llame a "PySet_New()" y "PyFrozenSet_New()" para crear un nuevo conjunto, "PySet_Add()" y "PySet_Discard()" para añadir y eliminar elementos, y "PySet_Contains()" y "PySet_Size()" para examinar el estado del conjunto. (Contribución de Raymond Hettinger)
-
El código C puede ahora obtener información sobre la revisión exacta del intérprete de Python llamando a la función "Py_GetBuildInfo()" que devuelve una cadena de información de compilación como esta ""trunk:45355:45356M, Apr 13 2006, 07:42:19"". (Contribuido por Barry Warsaw.)
-
Two new macros can be used to indicate C functions that are local to the current file so that a faster calling convention can be used. "Py_LOCAL" declares the function as returning a value of the specified type and uses a fast-calling qualifier. "Py_LOCAL_INLINE" does the same thing and also requests the function be inlined. If macro "PY_LOCAL_AGGRESSIVE" is defined before "python.h" is included, a set of more aggressive optimizations are enabled for the module; you should benchmark the results to find out if these optimizations actually make the code faster. (Contributed by Fredrik Lundh at the NeedForSpeed sprint.)
-
"PyErr_NewException(name, base, dict)" ahora puede aceptar una tupla de clases base como su argumento base. (Contribuido por Georg Brandl.)
-
La función "PyErr_Warn()" para emitir avisos está ahora obsoleta en favor de "PyErr_WarnEx(category, message, stacklevel)" que permite especificar el número de marcos de pila que separan esta función y la que la llama. Un stacklevel de 1 es la función que llama a "PyErr_WarnEx()", 2 es la función que está por encima, y así sucesivamente. (Añadido por Neal Norwitz.)
-
El intérprete de CPython sigue estando escrito en C, pero el código ahora puede ser compilado con un compilador de C++ sin errores. (Implementado por Anthony Baxter, Martin von Löwis, Skip Montanaro)
-
Se ha eliminado la función "PyRange_New()". Nunca se documentó, nunca se utilizó en el código del núcleo, y tenía una comprobación de errores peligrosamente laxa. En el improbable caso de que sus extensiones la utilizaran, puede sustituirla por algo como lo siguiente:
range = PyObject_CallFunction((PyObject*) &PyRange_Type, "lll", start, stop, step);
Cambios específicos en los puertos#
-
MacOS X (10.3 y superior): la carga dinámica de módulos utiliza ahora la función "dlopen()" en lugar de funciones específicas de MacOS.
-
MacOS X: se ha añadido una opción "--enable-universalsdk" al script configure que compila el intérprete como un binario universal capaz de funcionar tanto en procesadores PowerPC como Intel. (Contribución de Ronald Oussoren; bpo-2573.)
-
Windows: ".dll" ya no se admite como extensión de nombre de archivo para los módulos de extensión. ".pyd" es ahora la única extensión de nombre de archivo que se buscará.
Adaptación a Python 2.5#
Esta sección enumera los cambios descritos anteriormente que pueden requerir cambios en su código:
-
ASCII es ahora la codificación por defecto para los módulos. Ahora es un error de sintaxis si un módulo contiene literales de cadena con caracteres de 8 bits pero no tiene una declaración de codificación. En Python 2.4 esto provocaba una advertencia, no un error de sintaxis.
-
Previously, the "gi_frame" attribute of a generator was always a frame object. Because of the PEP 342 changes described in section PEP 342: Nuevas funciones del generador, it's now possible for "gi_frame" to be "None".
-
Una nueva advertencia, "UnicodeWarning", se lanza cuando se intenta comparar una cadena Unicode y una cadena de 8 bits que no puede ser convertida a Unicode utilizando la codificación ASCII por defecto. Anteriormente estas comparaciones lanzaban una excepción "UnicodeDecodeError".
-
Biblioteca: el módulo "csv" es ahora más estricto con los campos citados en varias líneas. Si sus archivos contienen nuevas líneas incrustadas dentro de los campos, la entrada debe dividirse en líneas de manera que se conserven los caracteres de nueva línea.
-
Biblioteca: la función "format()" del módulo "locale" aceptaba antes cualquier cadena siempre que no apareciera más de un especificador %char. En Python 2.5, el argumento debe ser exactamente un especificador %char sin texto alrededor.
-
Biblioteca: Los módulos "pickle" y "cPickle" ya no aceptan un valor de retorno de "None" del método "reduce()"; en su lugar, el método debe devolver una tupla de argumentos. Los módulos tampoco aceptan el parámetro de palabra clave bin, que ya no se utiliza.
-
Library: The "SimpleXMLRPCServer" and "DocXMLRPCServer" classes now have a "rpc_paths" attribute that constrains XML-RPC operations to a limited set of URL paths; the default is to allow only "'/'" and "'/RPC2'". Setting "rpc_paths" to "None" or an empty tuple disables this path checking.
-
API de C: muchas funciones ahora usan "Py_ssize_t" en lugar de int para permitir el procesamiento de más datos en máquinas de 64 bits. Es posible que el código de extensión deba realizar el mismo cambio para evitar advertencias y admitir máquinas de 64 bits. Consulte la sección anterior PEP 353: Uso de ssize_t como tipo de índice para obtener una explicación de este cambio.
-
API C: Los cambios en obmalloc significan que debe tener cuidado de no mezclar el uso de las familias de funciones "PyMem_" y "PyObject_". La memoria asignada con la función "_Malloc" de una familia, debe ser liberada con la función "_Free" de la familia correspondiente.
Agradecimientos#
El autor desea agradecer a las siguientes personas sus sugerencias, correcciones y ayuda en varios borradores de este artículo: Georg Brandl, Nick Coghlan, Phillip J. Eby, Lars Gustäbel, Raymond Hettinger, Ralf W. Grosse-Kunstleve, Kent Johnson, Iain Lowe, Martin von Löwis, Fredrik Lundh, Andrew McNamara, Skip Montanaro, Gustavo Niemeyer, Paul Prescod, James Pryor, Mike Rovner, Scott Weikart, Barry Warsaw, Thomas Wouters.