Re: [pyar] Re: whyname corregido

Top Page
Attachments:
+ (text/plain)
Delete this message
Reply to this message
Author: Daniel F Moisset
Date:  
To: pyar
Subject: Re: [pyar] Re: whyname corregido
On Mon, 2008-10-06 at 16:04 -0300, Facundo Batista wrote:
> El día 6 de octubre de 2008 15:46, Daniel F Moisset
> <> escribió:
>
> > La pena es que en Python es muy difícil, dado que para que sea efectivo
> > requiere que la cultura (y en particular, la biblioteca estándar) sea
> > más o menos coherente con esta idea, en vez de levantar excepciones por
> > boludeces como "hiciste open() a un archivo inexistente".
>
> Estoy de acuerdo con todo lo que dijiste antes, pero no con esta última frase.
>
> En tu opinión, ¿qué debería hacer open() si le pasás un archivo que no existe?


Voy a contestar al revés, diciendo en que caso sí se deberían dar
excepciones. En general, cuando es evidente que cagaste la fruta:

A) Tratás de evaluar una función fuera de su dominio. Por ejemplo
math.sqrt(-1), 1/0, dict.__getitem__(d, k) cuando k no es una clave de
d, f.write("Hola mundo") cuando f es un archivo abierto sólo para
lectura o persona.barrer() cuando len(persona.escobas)==0.
B) Te vino algún mensaje genérico externo que no sabés manejar; por ej
una señal del sistema operativo de las graves. O un "te quedaste sin
memoria"
C) Algún chequeo de consistencia interno falla: puede ser un assert en
tu código, o que el runtime de repente se encontró con un reference
count que era -47.

Los casos del punto A) son todos casos que deberías poder prevenir. Si
prevenís esos casos, todo lo que queda son situaciones catastróficas (se
pinchó el interpreté, se acabó la memoria, te pasaste del tiempo de CPU
permitido, o se acabó el café).

El open() a primera vista puede parecer un ejemplo del primer caso;
podrías decir "open no está definido sobre nombres de archivos que no
están en el disco". Pero no hay forma de hacer una llamada a open() y
estar seguro de que va a funcionar, no importa cuan buenos sean tus
algoritmos y cuantos chequeos pongas antes de la llamada. Aunque acabes
de crear el archivo, y por las dudas le hagas un stat() para ver que
esta ahí, y un access() para ver que tengas permisos, capaz para el
momento de hacerle open() un sysadmin chistoso lo borró.

Eso es porque en la mayoría de los systemas modernos, la semántica de la
syscall open() no es "abrí un archivo", sino, "tratá de abrir un
archivo". Que el archivo no exista no es una excepción ni una
catástrofe. Me pasa todos los días, y muchas veces uno tiene
alternativas de hacer las cosas.

Mi función favorita de abrir archivos de stdlib se puede llamar open,
pero lo que hace es "devuelve un archivo, en lo posible abierto". O sea,
un objetito muy parecido al que se engancha ahora a f si hago:

f = open('/etc/passwd'); f.close()

No es una excepción tratar de abrir un archivo. Si es una excepción
tratar de leer de un archivo cerrado (algo que si querés podés ver antes
de leer). O sea, si haces:

data = open('archivo').read()

puede o andar o fallar con una excepción (cuya descripción dirá algo
como read: 'archivo' no estaba abierto). O explotar con "inconsistencia
en el ECC del cache L2" o algún problema más serio.

si querés manejar alternativas (que ahora no son excepciones, usas if)

f = open(self.some_file_name)
if not f.closed:
    data = f.read()
else:
    data = 'default'


Que para mi es lo explícito que hace falta, no inventa flujo de control,
y es mejor que:

try:
    f = open(self.some_file_name)
    data = f.read()
except IOError:
    data = 'default'
# Y si quiero manejar distintos casos de IOError, tengo que poner ifs en
# el except, pero en otros casos tengo que en vez poner más clausulas 
# except....
# Y podrá ser que self.some_file_name me levante un IOError? y en
# herederos? Y en implementaciones futuras? voy a tener que escribir un
# test case para cubrir esto? O inventar una variable local para asignar
# el nombre antes?



Saludos,
    D.


PD: Python ya _casi_ hace lo que tiene que hacer

In [4]: f = open('/etc/passwd')
In [5]: f.close()
In [6]: f.closed
Out[6]: True
In [7]: f.read()
---------------------------------------------------------------------------
<type 'exceptions.ValueError'>            Traceback (most recent call
last)


/home/dmoisset/<ipython console> in <module>()

<type 'exceptions.ValueError'>: I/O operation on closed file



---------------------------------------------------------------------
Para dar de baja la suscripcion, mande un mensaje a:


Para obtener el resto de direcciones-comando, mande un mensaje a:


PyAr - Python Argentina - Sitio web: http://www.python.com.ar/