PyMOTW: exceptions
21 Septiembre 2008
Traducción de PyMOTW: exceptions, el módulo exceptions de la columna semanal de Doug Hellmann.
| Módulo | exceptions |
|---|---|
| Propósito | El módulo exceptions define los errores incorporados que se usan en la biblioteca estándar y por el intérprete. |
| Versión de Python | 1.5 y posterior |
Descripción
En el pasado, Python ha soportado cadenas simples de mensajes como excepciones
así como clases. Desde la versión 1.5, todos los módulos de la biblioteca
estándar usan clases para excepciones. A partir de Python 2.5, excepciones de
cadenas resultan en una advertencia DeprecationWarning, y el soporte para
excepciones de cadenas va a ser retirado en el futuro.
Clases base
Las clases de excepciones están definidas en una jerarquía, que está descrita en la documentación de la biblioteca estándar. Adicionalmente a los beneficios obvios de organización, la herencia de excepciones es útil porque excepciones relacionadas pueden ser atrapadas atrapando su clase base. En la mayoría de los casos, estas clases base no están destinadas a ser lanzadas directamente.
BaseException
Clase base para todas las excepciones. Implementa la lógica para crear una
cadena que represente la excepciones usando str() con los argumentos que se
pasan al constructor.
Exception
Clase base para excepciones que no resultan en la terminación de la aplicación
que se está ejecutando. Todas las excepciones definidas por el usuario
deberían usar Exception como clase base.
StandardError
Clase base para excepciones incorporadas usadas en la biblioteca estándar.
ArithmeticError
Clase base para errores matemáticos.
LookupError
Clase base para errores que son lanzados cuando algo no puede ser encontrado.
EnvironmentError
Clase base para errores que vienen de fuera de Python (el sistema operativo, el sistema de archivos, etc.).
Excepciones lanzadas
AssertionError
Un AssertionError es lanzado por una instrucción assert fallida.
assert False, 'La afirmación ha fallado'
$ python exceptions_AssertionError_assert.py
Traceback (most recent call last):
File "exceptions_AssertionError_assert.py", line 12, in <module>
assert False, 'La afirmación ha fallado'
AssertionError: La afirmación ha fallado
También es usado en el módulo unittest en métodos como failIf().
import unittest
class AssertionExample(unittest.TestCase):
def test(self):
self.failUnless(False)
unittest.main()
$ python exceptions_AssertionError_unittest.py
F
======================================================================
FAIL: test (__main__.AssertionExample)
----------------------------------------------------------------------
Traceback (most recent call last):
File "exceptions_AssertionError_unittest.py", line 17, in test
self.failUnless(False)
AssertionError
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures=1)
AttributeError
Cuando una referencia o una asignación a un atributo fallan, AttributeError es
lanzado.
Por ejemplo, cuando se trata de referencias a una atributo que no existe:
class NoAttributes(object):
pass
o = NoAttributes()
print o.attribute
$ python exceptions_AttributeError.py
Traceback (most recent call last):
File "exceptions_AttributeError.py", line 16, in <module>
print o.attribute
AttributeError: 'NoAttributes' object has no attribute 'attribute'
O cuando se trata de modificar un atributo sólo de lectura.
class MyClass(object):
@property
def attribute(self):
return 'Este es el valor de attribute'
o = MyClass()
print o.attribute
o.attribute = 'Nuevo valor'
$ python exceptions_AttributeError_assignment.py
Este es el valor de attribute
Traceback (most recent call last):
File "exceptions_AttributeError_assignment.py", line 20, in <module>
o.attribute = 'Nuevo valor'
AttributeError: can't set attribute
EOFError
Un EOFError es lanzado cuando una función incorporada como input() o
raw_input() no lee ningún dato antes de encontrar en final de su flujo de
entrada. Los métodos de archivo como read() devuelven una cadena vacía al
final del archivo.
while True:
data = raw_input('prompt:')
print 'LEIDO:', data
$ echo hello | python exceptions/exceptions_EOFError.py
prompt:LEIDO: hello
prompt:Traceback (most recent call last):
File "exceptions_EOFError.py", line 13, in <module>
data = raw_input('prompt:')
EOFError: EOF when reading a line
FloatingPointError
Es lanzada por operaciones con números de coma flotante que resultan en
errores, cuando el control de excepción de coma flotante (fpectl, floating
point exception control) está activado. Activar fpectl requiere de un
intérprete compilado con --with-fpectl. El uso de fpectl no se recomienda
en la documentación de la biblioteca estándar
http://docs.python.org/lib/module-fpectl.html.
import math
import fpectl
print 'Control desactivado:', math.exp(1000)
fpectl.turnon_sigfpe()
print 'Control activado:', math.exp(1000)
GeneratorExit
Es lanzada dentro de un generador si el método close() del generador es
invocado.
def my_generator():
try:
for i in range(5):
print 'Rindiendo', i
yield i
except GeneratorExit:
print 'Saliendo anticipadamente'
g = my_generator()
print g.next()
g.close()
$ python exceptions_GeneratorExit.py
Rindiendo 0
0
Saliendo anticipadamente
IOError
Es lanzada cuando la entrada o salida fallan, por ejemplo si un disco se llena o un archivo de entrada no existe.
f = open('/no/existe', 'r')
$ python exceptions_IOError.py
Traceback (most recent call last):
File "exceptions_IOError.py", line 12, in <module>
f = open('/no/existe', 'r')
IOError: [Errno 2] No such file or directory: '/no/existe'
ImportError
Es lanzada cuando un módulo, o un miembro de un módulo no puede ser importado.
Hay algunas condiciones en las que ImportError puede ser lanzada.
Si un módulo no existe.
import module_no_existe
$ python exceptions_ImportError_nomodule.py Traceback (most recent call last): File "exceptions_ImportError_nomodule.py", line 12, in
import module_no_existe ImportError: No module named module_no_existe Si
from X import Yes usado yYno puede ser encontrado dentro del móduloX, unImportErrores lanzado.from exceptions import NombreInventado
$ python exceptions_ImportError_missingname.py Traceback (most recent call last): File "exceptions_ImportError_missingname.py", line 12, in
from exceptions import NombreInventado ImportError: cannot import name NombreInventado
IndexError
Un IndexError es lanzado cuando una referencias en una secuencia está fuera
de rango.
my_seq = [ 0, 1, 2 ]
print my_seq[3]
$ python exceptions_IndexError.py
Traceback (most recent call last):
File "exceptions_IndexError.py", line 13, in <module>
print my_seq[3]
IndexError: list index out of range
KeyError
De manera similar, un KeyError es lanzado cuando un valor no es encontrado
como llave de un diccionario.
d = { 'a':1, 'b':2 }
print d['c']
$ python exceptions_KeyError.py
Traceback (most recent call last):
File "exceptions_KeyError.py", line 13, in <module>
print d['c']
KeyError: 'c'
KeyboardInterrupt
Un KeyboardInterrupt ocurre cuando el usuario presiona Control-C (o Delete)
para detener un programa en ejecución. A diferencias de la mayoría de las
excepciones, KeyboardInterrupt se deriva directamente de BaseException para
evitar ser atrapada por gestores de excepción globales que atrapan Exception.
try:
print 'Presiona Return o Control-C:',
ignored = raw_input()
except Exception, err:
print 'Excepción atrapada:', err
except KeyboardInterrupt, err:
print 'Excepción KeyboardInterrupt'
else:
print 'Ninguna excepción'
Presionando Control-C en la consola ocasiona una excepción KeyboardInterrupt.
$ python exceptions_KeyboardInterrupt.py
Presiona Return o Control-C: Excepción KeyboardInterrupt
MemoryError
Si tu programa se queda sin memoria y es posible recuperarse (eliminando
algunos objetos, por ejemplo), un MemoryError es lanzado.
import itertools
# Intenta crear un MemoryError asignando un montón de memoria
l = []
for i in range(3):
try:
for j in itertools.count(1):
print i, j
l.append('*' * (2**30))
except MemoryError:
print '(error, descartando la lista existente)'
l = []
$ python exceptions_MemoryError.py
0 1
0 2
(error, descartando la lista existente)
1 1
1 2
(error, descartando la lista existente)
2 1
2 2
(error, descartando la lista existente)
NameError
NameErrors son lanzados cuando tu código hace referencia a un nombre que no
existe en el ámbito (scope) actual. Por ejemplo, el nombre de una variable.
def func():
print nombre_desconocido
func()
$ python exceptions_NameError.py
Traceback (most recent call last):
File "exceptions_NameError.py", line 15, in <module>
func()
File "exceptions_NameError.py", line 13, in func
print nombre_desconocido
NameError: global name 'nombre_desconocido' is not defined
NotImplementedError
Clases base definidas por el usuario pueden lanzar NotImplementedError para
indicar que un método o comportamiento tiene que ser definido por una sub
clase, simulado así una interfaz.
class BaseClass(object):
"""Define la interfaz"""
def __init__(self):
super(BaseClass, self).__init__()
def do_something(self):
"""La interfaz, sin implementar"""
raise NotImplementedError(self.__class__.__name__ + '.do_something')
class SubClass(BaseClass):
"""Implementa la interfaz"""
def do_something(self):
"""hace algo de verdad"""
print self.__class__.__name__ + ' doing something!'
SubClass().do_something()
BaseClass().do_something()
$ python exceptions_NotImplementedError.py
SubClass haciendo algo!
Traceback (most recent call last):
File "exceptions_NotImplementedError.py", line 27, in <module>
BaseClass().do_something()
File "exceptions_NotImplementedError.py", line 18, in do_something
raise NotImplementedError(self.__class__.__name__ + '.do_something')
NotImplementedError: BaseClass.do_something
OSError
OSError sirve como la clase de error para el módulo os, y es lanzado cuando
un error surge de una función específica del sistema operativo.
import os
for i in range(10):
print i, os.ttyname(i)
$ python exceptions_OSError.py
0 /dev/pts/0
1 /dev/pts/0
2 /dev/pts/0
3
Traceback (most recent call last):
File "exceptions_OSError.py", line 15, in <module>
print i, os.ttyname(i)
OSError: [Errno 9] Bad file descriptor
OverflowError
Cuando una operación aritmética supera los límites del tipo de variable, un
OverflowError es lanzado. Número enteros grandes asignan más espacio a
medida que los valores crece, entonces terminan lanzando MemoryError. La
gestión de excepciones de números de coma flotante no está estandarizada,
entonces los números de coma flotante no se comprueban. Número enteros
normales son convertidos a valores long según sea necesario.
import sys
print 'Número entereo normal: (maxint=%s)' % sys.maxint
try:
i = sys.maxint * 3
print 'Sin rebalse para ', type(i), 'i =', i
except OverflowError, err:
print 'Rebalse en ', i, err
print
print 'Número entero largo:'
for i in range(0, 100, 10):
print '%2d' % i, 2L ** i
print
print 'Valores de coma flotante:'
try:
f = 2.0**i
for i in range(100):
print i, f
f = f ** 2
except OverflowError, err:
print 'Rebalse luego de ', f, err
$ python exceptions_OverflowError.py
Número entereo normal: (maxint=2147483647)
Sin rebalse para <type 'long'> i = 6442450941
Número entero largo:
0 1
10 1024
20 1048576
30 1073741824
40 1099511627776
50 1125899906842624
60 1152921504606846976
70 1180591620717411303424
80 1208925819614629174706176
90 1237940039285380274899124224
Valores de coma flotante:
0 1.23794003929e+27
1 1.53249554087e+54
2 2.34854258277e+108
3 5.5156522631e+216
Rebalse luego de 5.5156522631e+216 (34, 'Numerical result out of range')
ReferenceError
Cuando un proxy weakref es usado para acceder a un objeto que ya ha sido
recolectado (garbage collected), un ReferenceError ocurre.
import gc
import weakref
class ExpensiveObject(object):
def __init__(self, name):
self.name = name
def __del__(self):
print '(Borrando %s)' % self
obj = ExpensiveObject('obj')
p = weakref.proxy(obj)
print 'ANTES:', p.name
obj = None
print 'DESPUÉS:', p.name
$ python exceptions_ReferenceError.py
ANTES: obj
(Borrando <__main__.ExpensiveObject object at 0xb7d1d64c>)
DESPUÉS:
Traceback (most recent call last):
File "exceptions_ReferenceError.py", line 26, in <module>
print 'DESPUÉS:', p.name
ReferenceError: weakly-referenced object no longer exists
RuntimeError
Una excepción RuntimeError es usada cuando ninguna otra excepción más
específica es aplicable. El intérprete no lanza esta excepción con mucha
frecuencia, pero código de usuario lo hace.
StopIteration
Cuando un iterador ha terminado, su método next() lanza StopIteration.
Esta excepción no es considerada un error.
l=[0,1,2]
i=iter(l)
print i
print i.next()
print i.next()
print i.next()
print i.next()
$ python exceptions_StopIteration.py
<listiterator object at 0xb7d6fb2c>
0
1
2
Traceback (most recent call last):
File "exceptions_StopIteration.py", line 19, in <module>
print i.next()
StopIteration
SyntaxError
Un SyntaxError ocurre cada vez que el analizador (parser) encuentra código
fuente que no entiende. Esto puede ser al importar un módulo, invocando
exec, o invocando eval(). Los atributos de la excepción pueden ser usados
para encontrar exactamente qué parte del texto de entrada ocasionó la
excepción.
try:
print eval('cinco por tres')
except SyntaxError, err:
print 'Error de sintaxis %s (%s-%s): %s' % \
(err.filename, err.lineno, err.offset, err.text)
print err
$ python exceptions_SyntaxError.py
Error de sintáxis <string> (1-9): cinco por tres
invalid syntax (<string>, line 1)
SystemError
Cuando un error ocurre en el intérprete mismo y hay alguna oportunidad de
continuar la ejecución con éxito, lanza un SystemError. SystemErrors
probablemente indican una falla (bug) en el intérprete y deberían ser
reportados al mantenedor.
SystemExit
Cuando sys.exit() es invocada, lanza SystemExit en lugar de salir
inmediatamente. Esto permite ejecutar código de limpieza en bloques
try:finally y a los que invocan el código (como depuradores y frameworks de
prueba) capturar las excepciones y evitan salir.
TypeError
TypeErrors son ocasionados al combinar tipos equivocados de objetos o
invocando una función con el tipo de objeto equivocado.
result = ('tupla',) + 'cadena'
$ python exceptions_TypeError.py
Traceback (most recent call last):
File "exceptions_TypeError.py", line 12, in <module>
result = ('tupla',) + 'cadena'
TypeError: can only concatenate tuple (not "str") to tuple
UnboundLocalError
Un UnboundLocalError es un tipo de NameError específico para nombres de
variables locales.
def throws_global_name_error():
print unknown_global_name
def throws_unbound_local():
local_val = local_val + 1
print local_val
try:
throws_global_name_error()
except NameError, err:
print 'Error de nombre global:', err
try:
throws_unbound_local()
except UnboundLocalError, err:
print 'Error de nombre local:', err
La diferencia entre el NameError global y el UnboundLocalError es la manera
en que el nombre es usado. Ya que el nombre "local_val" aparece en el lado
izquierdo de una expresión, es interpretada como un nombre de variable local.
$ python exceptions_UnboundLocalError.py
Error de nombre global: global name 'unknown_global_name' is not defined
Error de nombre local: local variable 'local_val' referenced before assignment
UnicodeError
UnicodeError es una sub clase de ValueError y es lanzado cuando surge un
problema con Unicode. Hay clases sub clases separadas para
UnicodeEncodeError, UnicodeDecodeError, y UnicodeTranslateError.
ValueError
Un ValueError es usado cuando una función recibe un valor que tiene el tipo
correcto pero un valor inválido.
print chr(1024)
$ python exceptions_ValueError.py
Traceback (most recent call last):
File "exceptions_ValueError.py", line 12, in <module>
print chr(1024)
ValueError: chr() arg not in range(256)
ZeroDivisionError
Cuando cero aparece en el denominador de una operación de división, un
ZeroDivisionError es lanzado.
print 1/0
$ python exceptions_ZeroDivisionError.py
Traceback (most recent call last):
File "exceptions_ZeroDivisionError.py", line 12, in <module>
print 1/0
ZeroDivisionError: integer division or modulo by zero
Categorías de Warning
También hay varias excepciones definidas para ser usadas con el módulo warnings.
- Warning
- La clase base para todas las advertencias (*warnings*).
- UserWarning
- Clase base para advertencias que surgen en código del usuario.
- DeprecationWarning
- Usada para características que ya no están siendo mantenidas.
- PendingDeprecationWarning
- Usada para características que van a ser obsoletas pronto.
- SyntaxWarning
- Usada para sintáxis dudosa.
- RuntimeWarning
- Usada para para eventos que suceden en la ejecución que pueden causar problemas.
- FutureWarning
- Advertencia sobre cambios al lenguaje o la biblioteca en el futuro.
- ImportWarning
- Advertencia sobre problemas al importar un módulo.
- UnicodeWarning
- Advertencia sobre problemas con texto unicode.
Referencias
Documentación biblioteca estándar: exceptions
Copyright 2008 Doug Hellmann
blog comments powered by Disqus
