Discussion:
whyname corregido
(too old to reply)
Juan B Cabral
2008-10-03 19:34:18 UTC
Permalink
Corregi mi proyecto dadas las sugerencias de los Igores[0] voluntarios

cuando el codigo tenga 0 criticas me dedicare a la documentacion y
distribucin (recordemos que aun estoy aprendiendo y le pongo pilas para
dejar el mejor producto posible)

ahora respondo algunas preguntas:

1 - el tema de por que meto tanto la pata con los except son costumbres
java (ya se van a ir) de todas maneras dejo unos raise para algunos
tipos de exceptions que no se que no debo hacer nada.

2 - mi costumbre de toReturn, toWrite... viene principalmente de una
confusion que tube con un profe de la facu. el tipo en su perra vida
identificaba la variable donde resolvia la funcion. Con eso dejo muy en
claro y nunca mas se confundio. A mi particularmente me resulta muy muy
comodo que si tengo un metodo "get_wawawa()" si adentro hay una var del
tipo "toReturn" es esa la variable donde se carga todo lo que se "debe"
cargar... es cuestion de gustos... a lo sumo la adaptare mas a lo python
como "to_return". pero simplementem me gusta

gracuas a los igores y se agradecen que "sigan bajando" la palanca para
ver si la critura vive.(osea sigan criticando)

ya implementare el optparse esta noche o mañana

JuanBC

[0] http://en.wikipedia.org/wiki/Igor_(fictional_character)
Juan B Cabral
2008-10-03 19:41:24 UTC
Permalink
y como buen inteligente que soy aca recien va el link

http://code.google.com/p/whyname/
Gabriel Genellina
2008-10-03 21:29:51 UTC
Permalink
En Fri, 03 Oct 2008 16:34:18 -0300, Juan B Cabral
Post by Juan B Cabral
Corregi mi proyecto dadas las sugerencias de los Igores[0] voluntarios
cuando el codigo tenga 0 criticas me dedicare a la documentacion y
distribucin (recordemos que aun estoy aprendiendo y le pongo pilas para
dejar el mejor producto posible)
1 - el tema de por que meto tanto la pata con los except son costumbres
java (ya se van a ir) de todas maneras dejo unos raise para algunos
tipos de exceptions que no se que no debo hacer nada.
Java tiene excepciones chequeadas (una metida de pata de diseño) y
entonces es re comun que haya que atrapar todas las excepciones que
aparecen nada mas para cambiarles el tipo. Eso para lo unico que sirve es
para esconder informacion valiosa (como cuál fue el verdadero error
original), o induce a que los programadores escriban [el equivalente a]
esto:
try: ...
except: pass
que es como esconder el polvo abajo de la alfombra.

En Python la regla sería, parafraseando a mi abuela: "Si no tenes nada
bueno que hacer con la excepcion, sencillamente no la atrapes". Que siga
su curso, hasta que alguien más arriba con mas "contexto" la atrape y haga
algo útil.

En este ejemplo:

def get_whyname():
toReturn = _get_hostname() + ":\n\t"
try:
toReturn += _read_file()
except IOError, e:
if e.errno == 2 or e.errno == 21:
toReturn += 'A name policy has not been defined.'
else:
raise e
except:
raise
return toReturn

El except: raise esta de mas, lo podes sacar y no pasa nada. O sea: una
clausula except que *solo* contiene un raise, es totalmente transparente,
como si no existiera; solo sirve para alargar el codigo en numero de
lineas y en tiempo de ejecucion.
El `raise e` de mas arriba, sí deberia ser un raise pelado. Tal como está
ahora, el error "nace" en la linea que dice `raise e`, y eso es lo que te
mostraria un traceback. Pero en realidad es anterior, el error saltó al
intentar abrir el archivo, y sería bueno que te lo muestre así. Para eso
usas `raise`, a secas, que lanza la ultima excepcion manteniendo el
traceback completo original.

Otra cosa es que esta mezclado en el script principal, si start()
*imprime* un texto o *devuelve* un texto (en caso de error, imprime y
devuelve). En general, diria que start() y _get_response tienen
responsabilidades mezcladas (podrías decir *que* hace cada una en una sola
oracion?).

Y en general, yo prefiero que los errores se propaguen a traves de
excepciones, y no a traves del valor retornado por la funcion. O sea, si
set_whyname_string no puede hacer lo que se supone que tiene que hacer,
entonces lanza una excepcion; vos en su lugar estas devolviendo el texto
"You not have permisions to read: \n\t" + path
Por ejemplo,si el que invoco set_whyname_string quiere saber si anduvo
bien o no, es dificil, hay que andar mirando el texto devuelto a ver si
tiene pinta de error. Y si no lo verificas en el mismo lugar en que
hiciste la llamada, perdiste - se pierde esa informacion. Eso es lo bueno
de usar excepciones (el tratamiento del problema se difiere hasta el
momento en que alguien esta en condiciones de hacer algo util, no hace
falta hacerlo en el mismisimo lugar en que se detectó).
Post by Juan B Cabral
2 - mi costumbre de toReturn, toWrite... viene principalmente de una
confusion que tube con un profe de la facu. el tipo en su perra vida
identificaba la variable donde resolvia la funcion. Con eso dejo muy en
claro y nunca mas se confundio. A mi particularmente me resulta muy muy
comodo que si tengo un metodo "get_wawawa()" si adentro hay una var del
tipo "toReturn" es esa la variable donde se carga todo lo que se "debe"
cargar... es cuestion de gustos... a lo sumo la adaptare mas a lo python
como "to_return". pero simplementem me gusta
Ok, yo dentro de get_wawawa() usaria una variable llamada wawawa para ir
guardando lo que voy a devolver... pero si, es cuestion de gustos nomas. A
veces uso result, porque la mitad del tiempo programo en Delphi.
Post by Juan B Cabral
gracuas a los igores y se agradecen que "sigan bajando" la palanca para
ver si la critura vive.(osea sigan criticando)
Estoy criticón, se nota? Pero va con onda... :)
--
Gabriel Genellina
Mariano Guerra
2008-10-03 22:17:56 UTC
Permalink
Java tiene excepciones chequeadas (una metida de pata de diseño) y entonces
es re comun que haya que atrapar todas las excepciones que aparecen nada mas
para cambiarles el tipo. Eso para lo unico que sirve es para esconder
informacion valiosa (como cuál fue el verdadero error original), o induce a
try: ...
except: pass
que es como esconder el polvo abajo de la alfombra.
En Python la regla sería, parafraseando a mi abuela: "Si no tenes nada bueno
que hacer con la excepcion, sencillamente no la atrapes". Que siga su curso,
hasta que alguien más arriba con mas "contexto" la atrape y haga algo útil.
quería agregar algo a la discusión, si bien es insoportable que el
lenguaje te obligue a tratar excepciones en todos lados o a reportar
explícitamente que no la vas a tratar, esta bueno que el lenguaje sea
capaz de averiguar y decirte cuales excepciones tira un método.
Por ejemplo, en C# no te reta si no tratas una excepción y no tenes
que declarar que la tiras, pero tampoco te dice cuales son las que
tira, lo que lleva a buscar las excepciones que tira en la
documentacion y el 99% del tiempo nadie escribe que excepciones puede
tirar por la simple razón de que documentar es un perno y que de
arranque no sabes que excepciones tiran los métodos que usas vos.
A que voy con esto? me encantaría que python siga como es, pero que
si me interesa, me diga que excepciones pueden llegar a saltar, de esa
manera si realmente quiero hacer un try/except, puedo tratar las
excepciones de una forma "granular" y no hacer un except Exception
porque no se que puede saltar o ir agregando clausulas a medida que
saltan. :)

solo son deseos.. :D
Gabriel Genellina
2008-10-03 23:53:24 UTC
Permalink
En Fri, 03 Oct 2008 19:17:56 -0300, Mariano Guerra
2008/10/3 Gabriel Genellina
Post by Gabriel Genellina
En Fri, 03 Oct 2008 16:34:18 -0300, Juan B Cabral
En Python la regla sería, parafraseando a mi abuela: "Si no tenes nada bueno
que hacer con la excepcion, sencillamente no la atrapes". Que siga su curso,
hasta que alguien más arriba con mas "contexto" la atrape y haga algo útil.
quería agregar algo a la discusión, si bien es insoportable que el
lenguaje te obligue a tratar excepciones en todos lados o a reportar
explícitamente que no la vas a tratar, esta bueno que el lenguaje sea
capaz de averiguar y decirte cuales excepciones tira un método.
Por ejemplo, en C# no te reta si no tratas una excepción y no tenes
que declarar que la tiras, pero tampoco te dice cuales son las que
tira, lo que lleva a buscar las excepciones que tira en la
documentacion y el 99% del tiempo nadie escribe que excepciones puede
tirar por la simple razón de que documentar es un perno y que de
arranque no sabes que excepciones tiran los métodos que usas vos.
A que voy con esto? me encantaría que python siga como es, pero que
si me interesa, me diga que excepciones pueden llegar a saltar, de esa
manera si realmente quiero hacer un try/except, puedo tratar las
excepciones de una forma "granular" y no hacer un except Exception
porque no se que puede saltar o ir agregando clausulas a medida que
saltan. :)
Creo que estas enfocando el problema al reves. En general, no hace falta
que atrapes las excepciones que no conoces. Si vas a atrapar una excepcion
es porque queres hacer algo especifico con ella - si no tenes nada bueno
para hacer, no la atrapes y punto.
Si pensas que sí hace falta atraparla, es porque posiblemente estas
pensando en un modelo de ejecución donde los errores se propagan a traves
de un codigo de retorno (típicamente: 0=OK, 1=paso tal cosa, 2=paso tal
otra...). En un modelo basado en excepciones, esto no es asi: si sucede
algun problema, lo comunicas a traves de una excepcion, no de un codigo de
retorno. Y dejas que la excepcion siga su curso hasta que "alguien" la
atrape porque tiene algo "util" que hacer con ella.
Por ejemplo, tu funcion set_whyname_file ahora devuelve un *texto* de
error. Vos sentis la "necesidad" de atrapar todas las excepciones
posibles, para poder devolver un texto válido en cada caso. Si esa funcion
simplemente lanzara una excepcion cuando hay un problema (bien sea el
IOError original, o cualquier otra cosa), entonces no tendrias la
"necesidad" de atrapar nada.
En un lenguaje con buen soporte de excepciones como es Python (o C++ para
mencionar algun otro), ésa es la mejor forma. En otros lenguajes (como C
por ejemplo) no te queda otra que pasarte la vida chequeando codigos de
retorno una y otra vez, en todas y cada una de las funciones que llamas.
Te olvidaste de hacerlo en algun lado (porque se te paso, por ignorancia,
porque estabas cansado, porque pensaste "esto no puede fallar nunca"...) y
ya tu programa hace cualquier verdura y es dificil darse cuenta qué pasó...

Claro que hay situaciones donde realmente convendría saber cuáles
excepciones podrían suceder, pero en general es algo imposible de
determinar a priori. Cualquier funcion puede disparar cualquier excepcion,
y no hay forma de predecirlo. open(filename) *usualmente* falla con
IOError, pero si filename no es una string va a saltar un TypeError, y
siempre podria haber un MemoryError, y si el nombre "open" apunta a otro
objeto que no es la funcion predefinida "open" (como en la version
anterior de tu programa, que redefinia string y list como variables), el
resultado puede ser absolutamente cualquier cosa. Python es dinámico
también en este aspecto, asi que anda acostumbrándote...
solo son deseos.. :D
Estoy seguro de que con el tiempo se te van a pasar :)
--
Gabriel Genellina
Mariano Guerra
2008-10-04 02:01:35 UTC
Permalink
Post by Gabriel Genellina
En Fri, 03 Oct 2008 19:17:56 -0300, Mariano Guerra
Post by Mariano Guerra
Post by Gabriel Genellina
En Fri, 03 Oct 2008 16:34:18 -0300, Juan B Cabral
En Python la regla sería, parafraseando a mi abuela: "Si no tenes nada bueno
que hacer con la excepcion, sencillamente no la atrapes". Que siga su curso,
hasta que alguien más arriba con mas "contexto" la atrape y haga algo útil.
quería agregar algo a la discusión, si bien es insoportable que el
lenguaje te obligue a tratar excepciones en todos lados o a reportar
explícitamente que no la vas a tratar, esta bueno que el lenguaje sea
capaz de averiguar y decirte cuales excepciones tira un método.
Por ejemplo, en C# no te reta si no tratas una excepción y no tenes
que declarar que la tiras, pero tampoco te dice cuales son las que
tira, lo que lleva a buscar las excepciones que tira en la
documentacion y el 99% del tiempo nadie escribe que excepciones puede
tirar por la simple razón de que documentar es un perno y que de
arranque no sabes que excepciones tiran los métodos que usas vos.
A que voy con esto? me encantaría que python siga como es, pero que
si me interesa, me diga que excepciones pueden llegar a saltar, de esa
manera si realmente quiero hacer un try/except, puedo tratar las
excepciones de una forma "granular" y no hacer un except Exception
porque no se que puede saltar o ir agregando clausulas a medida que
saltan. :)
el que escribio el texto al que estas respondiendo soy yo, no el
creador del thread ni del programa. :D
Post by Gabriel Genellina
Creo que estas enfocando el problema al reves. En general, no hace falta que
atrapes las excepciones que no conoces. Si vas a atrapar una excepcion es
porque queres hacer algo especifico con ella - si no tenes nada bueno para
hacer, no la atrapes y punto.
Es que yo si las quiero atrapar y no se cuales son :D, para dejar mas
claro esto, te posteo un fragmento de un post que escribi en mi blog
hace mucho (estaba un poco enojado cuando lo escribi pero se rescata
el mensaje :P)

[Quote]si tenes una retorcida adicción a lanzar excepciones haceme el
favor de atraparlas, y si la vas a atrapar hace algo útil, no vale
atraparla y no hacer nada[/Qoute]

a lo que referia con retorcida adiccion es que alguien me metio un
raise cada 5 lineas de codigo en un modulo cada vez que algo no le
gustaba (digamos que en vez de hacer un if para ver si habia una
llave, tiraba una excepcion :P)
Post by Gabriel Genellina
Si pensas que sí hace falta atraparla, es porque posiblemente estas pensando
en un modelo de ejecución donde los errores se propagan a traves de un
codigo de retorno (típicamente: 0=OK, 1=paso tal cosa, 2=paso tal otra...).
Exactamente, soy partidario de lanzar excepciones en casos en los que
no puedo hacer nada para solucionar un problema (no tengo la
informacion necesaria, no es el lugar o requiero que alguien en el
stack de llamadas se entere), pero tambien soy partidario de atrapar
excepciones en el punto que corresponde haciendo lo necesario para
solucionar el problema, para evitar que la excepcion para arriba y me
termine haciendo funcionar mal el programa.
Post by Gabriel Genellina
En un modelo basado en excepciones, esto no es asi: si sucede algun
problema, lo comunicas a traves de una excepcion, no de un codigo de
retorno. Y dejas que la excepcion siga su curso hasta que "alguien" la
atrape porque tiene algo "util" que hacer con ella.
totalmente de acuerdo, el valor de retorno de una funcion lo veo como
el resultado de una funcion matematica, es el resultado de la
ejecucion de la funcion, no un medio para comunicar otras cosas..
Post by Gabriel Genellina
Por ejemplo, tu funcion set_whyname_file ahora devuelve un *texto* de error.
no es mia :D
Post by Gabriel Genellina
Vos sentis la "necesidad" de atrapar todas las excepciones posibles, para
poder devolver un texto válido en cada caso. Si esa funcion simplemente
lanzara una excepcion cuando hay un problema (bien sea el IOError original,
o cualquier otra cosa), entonces no tendrias la "necesidad" de atrapar nada.
no es mio :D, y para aclarar, no siento la necesidad de atrapar todas
las excepciones, solo tengo la necesidad de saber cuales son las
posibles excepciones que pueden saltar asi decido cuales tratar, me ha
pasado que despues de que un programa mio esta siendo usado por 6
meses me llega un bug report de una excepcion que salta en una parte y
agrego el try/except en el lugar adecuado, y a los 2 meses me llega
otro bug report con otra excepcion muy rara que salta en el mismo
lugar. Me gustaria saber cuando agrego los except cuales son las
excepciones que pueden saltar en ese lugar para tratar las que
considere "tratables" en ese punto. Ese era el punto de mi mail
anterior.
Post by Gabriel Genellina
En un lenguaje con buen soporte de excepciones como es Python (o C++ para
mencionar algun otro), ésa es la mejor forma. En otros lenguajes (como C por
ejemplo) no te queda otra que pasarte la vida chequeando codigos de retorno
una y otra vez, en todas y cada una de las funciones que llamas. Te
olvidaste de hacerlo en algun lado (porque se te paso, por ignorancia,
porque estabas cansado, porque pensaste "esto no puede fallar nunca"...) y
ya tu programa hace cualquier verdura y es dificil darse cuenta qué pasó...
totalmente de acuerdo (alguien chequea la salida de printf en C para
saber si se escribieron todos los caracteres? :D)
Post by Gabriel Genellina
Claro que hay situaciones donde realmente convendría saber cuáles
excepciones podrían suceder, pero en general es algo imposible de determinar
a priori.
Por esto me voy a tener que aguantar el odio de muchos, pero java lo
hace (o casi lo hace), no digo que sea perfecto, pero un metodo es un
arbol de llamadas a otros metodos, la forma mas simple seria recorrer
los metodos llamados y ver los raise (no es 100% efectivo, pero al
menos me da un hint de que puedo llegar a esperarme).
Post by Gabriel Genellina
Cualquier funcion puede disparar cualquier excepcion, y no hay
forma de predecirlo. open(filename) *usualmente* falla con IOError, pero si
filename no es una string va a saltar un TypeError, y siempre podria haber
un MemoryError, y si el nombre "open" apunta a otro objeto que no es la
funcion predefinida "open" (como en la version anterior de tu programa, que
redefinia string y list como variables), el resultado puede ser
absolutamente cualquier cosa. Python es dinámico también en este aspecto,
asi que anda acostumbrándote...
Estoy de acuerdo, a fin de clarificar digamos que hay tres tipos de
errores, los errores de operaciones (del tipo "no podes abrir ese
archivo" o "el archivo no existe"), las excepciones inherentes a un
lenguaje dinamico (del tipo "lo que pasaste es un tipo invalido", "no
existe el metodo x para la variable y" etc) y las excepciones
totalmente raras (del tipo "te quedaste sin memoria", "no se puede
escribir en standar output", o excepciones del interprete). A mi me
interesaria saber las excepciones operacionales o "resultantes de la
ejecucion valida del metodo pero que por razones diversas como la
combinacion de valores de las variables genera un estado de
excepcion".
Post by Gabriel Genellina
Post by Mariano Guerra
solo son deseos.. :D
Estoy seguro de que con el tiempo se te van a pasar :)
y si, me tengo que acostumbrar, pero me parece interesante discutir
las cosas buenas de otros lenguajes o cosas que nos gustaria ver en
nuestro lenguaje preferido.

Perdon por el post largo...

PD: para que quede mas claro (o menos ;) aca va un ejemplo, este es un
proyecto mio, primero vemos la cantidad de lineas:

$ wc -l *.py

<snip>

19096 total

ahora vemos la cantidad de excepts que use:

$ grep except *.py | wc -l

129

veran que no soy un fanatico de atrapar excepciones por deporte, pero
tampoco que me gusta que mi app se le cierre a alguien por una
excepcion que ni siquiera sabia que podia saltar en cierto punto
(vease mas arriba el tipo de excepciones de las que quiero saber)
Roberto Alsina
2008-10-04 02:42:07 UTC
Permalink
Post by Mariano Guerra
[Quote]si tenes una retorcida adicción a lanzar excepciones haceme el
favor de atraparlas, y si la vas a atrapar hace algo útil, no vale
atraparla y no hacer nada[/Qoute]
a lo que referia con retorcida adiccion es que alguien me metio un
raise cada 5 lineas de codigo en un modulo cada vez que algo no le
gustaba (digamos que en vez de hacer un if para ver si habia una
llave, tiraba una excepcion :P)
Y porqueestas usando ese codigo horrible entonces?
Si hace eso, lo mas probable es que sea mas laburo usarlo que reemplazarlo.
--
("\''/").__..-''"`-. . Roberto Alsina
`9_ 9 ) `-. ( ).`-._.`) KDE Developer (MFCH)
(_Y_.)' ._ ) `._`. " -.-' http://lateral.netmanagers.com.ar
_..`-'_..-_/ /-'_.' The 6,855th most popular site of Slovenia
(l)-'' ((i).' ((!.' according to alexa.com (27/5/2007)

Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it. --Brian W. Kernighan
Juan B Cabral
2008-10-04 03:13:30 UTC
Permalink
Post by Roberto Alsina
Post by Mariano Guerra
[Quote]si tenes una retorcida adicción a lanzar excepciones haceme el
favor de atraparlas, y si la vas a atrapar hace algo útil, no vale
atraparla y no hacer nada[/Qoute]
a lo que referia con retorcida adiccion es que alguien me metio un
raise cada 5 lineas de codigo en un modulo cada vez que algo no le
gustaba (digamos que en vez de hacer un if para ver si habia una
llave, tiraba una excepcion :P)
Y porqueestas usando ese codigo horrible entonces?
Si hace eso, lo mas probable es que sea mas laburo usarlo que reemplazarlo.
creo que hay una crisis de identidad acá, el proyecto es mio...
por que cada uno no agarra un método y lo deja como le parece que
debería... o algo asi... mariano si bien me ayudo un poco no hizo nada
de las chanchadas que hice yo
Mariano Guerra
2008-10-04 03:15:02 UTC
Permalink
On Fri, Oct 3, 2008 at 11:42 PM, Roberto Alsina
Post by Roberto Alsina
Post by Mariano Guerra
[Quote]si tenes una retorcida adicción a lanzar excepciones haceme el
favor de atraparlas, y si la vas a atrapar hace algo útil, no vale
atraparla y no hacer nada[/Qoute]
a lo que referia con retorcida adiccion es que alguien me metio un
raise cada 5 lineas de codigo en un modulo cada vez que algo no le
gustaba (digamos que en vez de hacer un if para ver si habia una
llave, tiraba una excepcion :P)
Y porqueestas usando ese codigo horrible entonces?
Si hace eso, lo mas probable es que sea mas laburo usarlo que reemplazarlo.
era mi modulo y el tenia permisos de commit en el svn, saque la
mayoria de los raises

aca esta el diff, diviertanse :D

http://emesene.svn.sourceforge.net/viewvc/emesene/trunk/emesene/emesenelib/ContactData.py?r1=428&r2=498

PD: lo que hice yo en ese cambio no fue lo mejor, pero al menos la app
no tiraba una excepcion cada 5 segundos...
Juan B Cabral
2008-10-04 03:29:30 UTC
Permalink
tengo la sensacion que me perdi de algo :P
Roberto Alsina
2008-10-04 12:30:49 UTC
Permalink
Post by Mariano Guerra
On Fri, Oct 3, 2008 at 11:42 PM, Roberto Alsina
Post by Roberto Alsina
Post by Mariano Guerra
[Quote]si tenes una retorcida adicción a lanzar excepciones haceme el
favor de atraparlas, y si la vas a atrapar hace algo útil, no vale
atraparla y no hacer nada[/Qoute]
a lo que referia con retorcida adiccion es que alguien me metio un
raise cada 5 lineas de codigo en un modulo cada vez que algo no le
gustaba (digamos que en vez de hacer un if para ver si habia una
llave, tiraba una excepcion :P)
Y porqueestas usando ese codigo horrible entonces?
Si hace eso, lo mas probable es que sea mas laburo usarlo que reemplazarlo.
era mi modulo y el tenia permisos de commit en el svn, saque la
mayoria de los raises
aca esta el diff, diviertanse :D
http://emesene.svn.sourceforge.net/viewvc/emesene/trunk/emesene/emesenelib/
ContactData.py?r1=428&r2=498
PD: lo que hice yo en ese cambio no fue lo mejor, pero al menos la app
no tiraba una excepcion cada 5 segundos...
Oops, perdon si ofendi, no era la idea. No me acuerdo quien dijo "las
excepciones son para casos excepcionales" :-)
--
("\''/").__..-''"`-. . Roberto Alsina
`9_ 9 ) `-. ( ).`-._.`) KDE Developer (MFCH)
(_Y_.)' ._ ) `._`. " -.-' http://lateral.netmanagers.com.ar
_..`-'_..-_/ /-'_.' The 6,855th most popular site of Slovenia
(l)-'' ((i).' ((!.' according to alexa.com (27/5/2007)

Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it. --Brian W. Kernighan
Juan B Cabral
2008-10-04 03:15:10 UTC
Permalink
ya fue otra correccion mas
Gabriel Genellina
2008-10-06 09:15:03 UTC
Permalink
En Fri, 03 Oct 2008 23:01:35 -0300, Mariano Guerra
2008/10/3 Gabriel Genellina
Post by Gabriel Genellina
En Fri, 03 Oct 2008 19:17:56 -0300, Mariano Guerra
2008/10/3 Gabriel Genellina
Post by Gabriel Genellina
En Fri, 03 Oct 2008 16:34:18 -0300, Juan B Cabral
En Python la regla sería, parafraseando a mi abuela: "Si no tenes nada bueno
que hacer con la excepcion, sencillamente no la atrapes". Que siga su curso,
hasta que alguien más arriba con mas "contexto" la atrape y haga algo útil.
quería agregar algo a la discusión, si bien es insoportable que el
lenguaje te obligue a tratar excepciones en todos lados o a reportar
explícitamente que no la vas a tratar, esta bueno que el lenguaje sea
capaz de averiguar y decirte cuales excepciones tira un método. [...]
el que escribio el texto al que estas respondiendo soy yo, no el
creador del thread ni del programa. :D
Perdon, mezcle todo y te atribui cosas que no eran tuyas! Igual parece que
en general pensamos parecido.

[...]
Es que yo si las quiero atrapar y no se cuales son :D, para dejar mas
claro esto, te posteo un fragmento de un post que escribi en mi blog
hace mucho (estaba un poco enojado cuando lo escribi pero se rescata
el mensaje :P)
[Quote]si tenes una retorcida adicción a lanzar excepciones haceme el
favor de atraparlas, y si la vas a atrapar hace algo útil, no vale
atraparla y no hacer nada[/Qoute]
a lo que referia con retorcida adiccion es que alguien me metio un
raise cada 5 lineas de codigo en un modulo cada vez que algo no le
gustaba (digamos que en vez de hacer un if para ver si habia una
llave, tiraba una excepcion :P)
Bueh, tampoco la pavada :)
A algunos hay que vacunarlos de excepcionitis - tanto por lanzarlas en
todo momento como por intentar atraparlas a todas, como si fueran
pokemones :)
no es mio :D, y para aclarar, no siento la necesidad de atrapar todas
las excepciones, solo tengo la necesidad de saber cuales son las
posibles excepciones que pueden saltar asi decido cuales tratar, me ha
pasado que despues de que un programa mio esta siendo usado por 6
meses me llega un bug report de una excepcion que salta en una parte y
agrego el try/except en el lugar adecuado, y a los 2 meses me llega
otro bug report con otra excepcion muy rara que salta en el mismo
lugar. Me gustaria saber cuando agrego los except cuales son las
excepciones que pueden saltar en ese lugar para tratar las que
considere "tratables" en ese punto. Ese era el punto de mi mail
anterior.
Si, perfecto, creo que lo unico que puedo decir es "Te acompaño en el
sentimiento" :) A mi tambien me paso... Pero no le encuentro solucion,
aparte de analizar todo el arbol de posibles llamadas y ver que cosa
podria fallar en cada lugar. Y como eso es dinamico, no se, lo veo dificil
de implementar...
Por esto me voy a tener que aguantar el odio de muchos, pero java lo
hace (o casi lo hace), no digo que sea perfecto, pero un metodo es un
arbol de llamadas a otros metodos, la forma mas simple seria recorrer
los metodos llamados y ver los raise (no es 100% efectivo, pero al
menos me da un hint de que puedo llegar a esperarme).
El problema es que en java queda perfectamente determinado al momento de
compilar, cuál metodo va a ser llamado, asi que se puede chequear; pero no
en Python. A veces la parte dinamica juega en contra. Por ahi se podria
escribir alguna herramienta que analice el codigo, como lo hace pylint o
pychecker, y tratar de determinar que funciones se llaman y cuales podrian
ser las excepciones en cada caso, e ir subiendo en el arbol... No conozco
ninguna que lo haga, si algun voluntario se ofrece a escribirla yo hago de
beta tester :)
Estoy de acuerdo, a fin de clarificar digamos que hay tres tipos de
errores, los errores de operaciones (del tipo "no podes abrir ese
archivo" o "el archivo no existe"), las excepciones inherentes a un
lenguaje dinamico (del tipo "lo que pasaste es un tipo invalido", "no
existe el metodo x para la variable y" etc) y las excepciones
totalmente raras (del tipo "te quedaste sin memoria", "no se puede
escribir en standar output", o excepciones del interprete). A mi me
interesaria saber las excepciones operacionales o "resultantes de la
ejecucion valida del metodo pero que por razones diversas como la
combinacion de valores de las variables genera un estado de
excepcion".
A mi tambien me gustaria :)
Post by Gabriel Genellina
solo son deseos.. :D
Estoy seguro de que con el tiempo se te van a pasar :)
y si, me tengo que acostumbrar, pero me parece interesante discutir
las cosas buenas de otros lenguajes o cosas que nos gustaria ver en
nuestro lenguaje preferido.
No, eso de arriba (de que se te pase) venia de mi confusion inicial sobre
quien habia escrito que cosa. No hay nada que se te tenga que pasar; tus
deseos son perfectamente validos (aunque un tanto dificiles de cumplir).
Perdon por el post largo...
(Uh, creo que yo escribi cosas mas largas todavia...)
tampoco que me gusta que mi app se le cierre a alguien por una
excepcion que ni siquiera sabia que podia saltar en cierto punto
(vease mas arriba el tipo de excepciones de las que quiero saber)
Yo diria que por lo general se puede evitar que se cierre la aplicacion.
Basicamente, si la aplicacion es un bucle, habria que rebuscarselas para
que a lo sumo falle una iteracion del bucle; a veces se puede. Si es tipo
GUI tiene un loop de eventos, y con un try/except al procesar cada evento
individual estarias cubierto (supongo que eso ya viene hecho en todas las
librerias; al menos con Tkinter y wx ya esta). Y si es algo tipo batch,
digamos que procesa un archivo, alcanzaria con atrapar todas las
excepciones al procesar cada linea individual. O cosas asi.
--
Gabriel Genellina
Mariano Guerra
2008-10-06 13:07:06 UTC
Permalink
Post by Gabriel Genellina
En Fri, 03 Oct 2008 23:01:35 -0300, Mariano Guerra
Post by Mariano Guerra
Post by Gabriel Genellina
En Fri, 03 Oct 2008 19:17:56 -0300, Mariano Guerra
Post by Gabriel Genellina
En Fri, 03 Oct 2008 16:34:18 -0300, Juan B Cabral
[snip]
Post by Gabriel Genellina
Bueh, tampoco la pavada :)
A algunos hay que vacunarlos de excepcionitis - tanto por lanzarlas en todo
momento como por intentar atraparlas a todas, como si fueran pokemones :)
me encanto lo de los pokemones :D, la voy a usar algun dia para ser claro :P
Post by Gabriel Genellina
Post by Mariano Guerra
no es mio :D, y para aclarar, no siento la necesidad de atrapar todas
las excepciones, solo tengo la necesidad de saber cuales son las
posibles excepciones que pueden saltar asi decido cuales tratar, me ha
pasado que despues de que un programa mio esta siendo usado por 6
meses me llega un bug report de una excepcion que salta en una parte y
agrego el try/except en el lugar adecuado, y a los 2 meses me llega
otro bug report con otra excepcion muy rara que salta en el mismo
lugar. Me gustaria saber cuando agrego los except cuales son las
excepciones que pueden saltar en ese lugar para tratar las que
considere "tratables" en ese punto. Ese era el punto de mi mail
anterior.
Si, perfecto, creo que lo unico que puedo decir es "Te acompaño en el
sentimiento" :) A mi tambien me paso... Pero no le encuentro solucion,
aparte de analizar todo el arbol de posibles llamadas y ver que cosa podria
fallar en cada lugar. Y como eso es dinamico, no se, lo veo dificil de
implementar...
si, tenes razon, me parece que lo que sacrificamos por un lenguaje
dinamico bien vale la pena. Lo que me parece raro es que no salto
alguien a decirme que con unit testing estaba bastante cubierto ;)
Post by Gabriel Genellina
Post by Mariano Guerra
Por esto me voy a tener que aguantar el odio de muchos, pero java lo
hace (o casi lo hace), no digo que sea perfecto, pero un metodo es un
arbol de llamadas a otros metodos, la forma mas simple seria recorrer
los metodos llamados y ver los raise (no es 100% efectivo, pero al
menos me da un hint de que puedo llegar a esperarme).
El problema es que en java queda perfectamente determinado al momento de
compilar, cuál metodo va a ser llamado, asi que se puede chequear; pero no
en Python. A veces la parte dinamica juega en contra. Por ahi se podria
escribir alguna herramienta que analice el codigo, como lo hace pylint o
pychecker, y tratar de determinar que funciones se llaman y cuales podrian
ser las excepciones en cada caso, e ir subiendo en el arbol... No conozco
ninguna que lo haga, si algun voluntario se ofrece a escribirla yo hago de
beta tester :)
2do beta tester.
Post by Gabriel Genellina
Post by Mariano Guerra
tampoco que me gusta que mi app se le cierre a alguien por una
excepcion que ni siquiera sabia que podia saltar en cierto punto
(vease mas arriba el tipo de excepciones de las que quiero saber)
Yo diria que por lo general se puede evitar que se cierre la aplicacion.
Basicamente, si la aplicacion es un bucle, habria que rebuscarselas para que
a lo sumo falle una iteracion del bucle; a veces se puede. Si es tipo GUI
tiene un loop de eventos, y con un try/except al procesar cada evento
individual estarias cubierto (supongo que eso ya viene hecho en todas las
librerias; al menos con Tkinter y wx ya esta). Y si es algo tipo batch,
digamos que procesa un archivo, alcanzaria con atrapar todas las excepciones
al procesar cada linea individual. O cosas asi.
Si gtk tambien lo maneja, lo que me suele pasar por ejemplo es que si
salta una excepcion bien abajo en el stack de llamadas que procesa la
llegada o salida de un mensaje el usuario no ve/envia el mensaje y eso
el usuario lo percibe como algo feito :D, nunca se me cerro la app,
igual usamos los hooks de excepciones para que el usuario vea que algo
malo paso

"Errors should never pass silently."
Ernesto Savoretti
2008-10-04 07:30:08 UTC
Permalink
El día 3 de octubre de 2008 20:53, Gabriel Genellina
Post by Gabriel Genellina
.....
En general, no hace falta que
atrapes las excepciones que no conoces. Si vas a atrapar una excepcion es
porque queres hacer algo especifico con ella - si no tenes nada bueno para
hacer, no la atrapes y punto.
Si pensas que sí hace falta atraparla, es porque posiblemente estas pensando
en un modelo de ejecución donde los errores se propagan a traves de un
codigo de retorno (típicamente: 0=OK, 1=paso tal cosa, 2=paso tal otra...).
En un modelo basado en excepciones, esto no es asi: si sucede algun
problema, lo comunicas a traves de una excepcion, no de un codigo de
retorno. Y dejas que la excepcion siga su curso hasta que "alguien" la
atrape porque tiene algo "util" que hacer con ella.
Por ejemplo, tu funcion set_whyname_file ahora devuelve un *texto* de error.
Vos sentis la "necesidad" de atrapar todas las excepciones posibles, para
poder devolver un texto válido en cada caso. Si esa funcion simplemente
lanzara una excepcion cuando hay un problema (bien sea el IOError original,
o cualquier otra cosa), entonces no tendrias la "necesidad" de atrapar nada.
En un lenguaje con buen soporte de excepciones como es Python (o C++ para
mencionar algun otro), ésa es la mejor forma. En otros lenguajes (como C por
ejemplo) no te queda otra que pasarte la vida chequeando codigos de retorno
una y otra vez, en todas y cada una de las funciones que llamas. Te
olvidaste de hacerlo en algun lado (porque se te paso, por ignorancia,
porque estabas cansado, porque pensaste "esto no puede fallar nunca"...) y
ya tu programa hace cualquier verdura y es dificil darse cuenta qué pasó...
Esto debería ir a algún "diccionario conceptual" o algo así (ya que no
es una receta como para ir al recetario) donde uno busque p. ej.
"excepciones" y esto salte, sólo o acompañado de otros conceptos. Pero
esto no deberìa perderse.
--
Ernesto Savoretti
Facundo Batista
2008-10-04 17:25:34 UTC
Permalink
El día 3 de octubre de 2008 20:53, Gabriel Genellina
Post by Gabriel Genellina
Creo que estas enfocando el problema al reves. En general, no hace falta que
atrapes las excepciones que no conoces. Si vas a atrapar una excepcion es
porque queres hacer algo especifico con ella - si no tenes nada bueno para
hacer, no la atrapes y punto.
+100
--
. Facundo

Blog: http://www.taniquetil.com.ar/plog/
PyAr: http://www.python.org/ar/
Juan B Cabral
2008-10-04 17:42:54 UTC
Permalink
Post by Ernesto Savoretti
El día 3 de octubre de 2008 20:53, Gabriel Genellina
Post by Gabriel Genellina
Creo que estas enfocando el problema al reves. En general, no hace falta que
atrapes las excepciones que no conoces. Si vas a atrapar una excepcion es
porque queres hacer algo especifico con ella - si no tenes nada bueno para
hacer, no la atrapes y punto.
+100
a esta altura es buen momento para preguntar... para quien es esa respuesta?

JuanBC
Daniel F Moisset
2008-10-06 18:46:20 UTC
Permalink
Post by Mariano Guerra
Java tiene excepciones chequeadas (una metida de pata de diseño) y entonces
es re comun que haya que atrapar todas las excepciones que aparecen nada mas
para cambiarles el tipo. Eso para lo unico que sirve es para esconder
informacion valiosa (como cuál fue el verdadero error original), o induce a
try: ...
except: pass
que es como esconder el polvo abajo de la alfombra.
En Python la regla sería, parafraseando a mi abuela: "Si no tenes nada bueno
que hacer con la excepcion, sencillamente no la atrapes". Que siga su curso,
hasta que alguien más arriba con mas "contexto" la atrape y haga algo útil.
quería agregar algo a la discusión, si bien es insoportable que el
lenguaje te obligue a tratar excepciones en todos lados o a reportar
explícitamente que no la vas a tratar, esta bueno que el lenguaje sea
capaz de averiguar y decirte cuales excepciones tira un método.
Son approaches distintos a manejo de excepciones...

Mi favorita es la versión espartana/minimalista, basada en "una rutina
tiene que hacer una sola cosa y hacerla bien". Eso, llevado a diseño de
un sistema de excepciones queda en:

* Una rutina tiene dos finales posibles: devuelve un valor, o falla
* Estos "fallos" no son objetos (del mismo modo que "dar la última
vuelta en un while" o "entrar por la rama else de este condicional" no
son objetos). Puede haber un objeto con algo de contexto del fallo
generado por el runtime, pero esto es algo más a nivel
runtime/biblioteca que a nivel lenguaje.
* La información esta es para debugging más que para control: Un fallo
quiere decir que se produjo una situación inesperada y muy desconocida.
Para manejar situaciones inusuales pero que son "esperadas" o
"conocidas" se usa el flujo de control usual (léase "if")
* Los fallos se manejan a nivel rutina, no a nivel bloque
* Una rutina puede manejar un fallo de dos formas posibles: propagar el
fallo (posiblemente haciendo cleanup), o recomponer el estado inicial y
reintentar.

Usar esto elimina la pregunta de Mariano "¿Que excepciones puede tirar
esta rutina?" y la preocupación por la Javitis de "tengo que manejar
_tooodas_ las excepciones", además de ser coherente con lo que dice
Gabriel de "cualquier funcion puede disparar cualquier excepcion,
y no hay forma de predecirlo [ejemplo de open()]".

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".

Saludos,
D.
Facundo Batista
2008-10-06 19:04:48 UTC
Permalink
El día 6 de octubre de 2008 15:46, Daniel F Moisset
Post by Daniel F Moisset
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?

Slds.
--
. Facundo

Blog: http://www.taniquetil.com.ar/plog/
PyAr: http://www.python.org/ar/
Juan B Cabral
2008-10-06 18:10:13 UTC
Permalink
Post by Facundo Batista
El día 6 de octubre de 2008 15:46, Daniel F Moisset
Post by Daniel F Moisset
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?
Slds.
cambiandole de titulo al thread por que me esta costando encontrar la
sugerencia a mi proyecto con tanta cosa de exception

dado que open devuelve una referencia a file, devolver a None seria
consistente

JuanBC
Facundo Batista
2008-10-06 19:17:20 UTC
Permalink
El día 6 de octubre de 2008 15:10, Juan B Cabral
Post by Juan B Cabral
Post by Facundo Batista
En tu opinión, ¿qué debería hacer open() si le pasás un archivo que no existe?
cambiandole de titulo al thread por que me esta costando encontrar la
sugerencia a mi proyecto con tanta cosa de exception
dado que open devuelve una referencia a file, devolver a None seria
consistente
En mi opinión, tener que revisar si lo que te devolvió es None cada
vez que abrís un archivo (o exponerte a errores peores luego), es poco
pythónico.

Slds.
--
. Facundo

Blog: http://www.taniquetil.com.ar/plog/
PyAr: http://www.python.org/ar/
Roberto Alsina
2008-10-06 19:23:06 UTC
Permalink
Post by Facundo Batista
El día 6 de octubre de 2008 15:10, Juan B Cabral
Post by Juan B Cabral
Post by Facundo Batista
En tu opinión, ¿qué debería hacer open() si le pasás un archivo que no existe?
cambiandole de titulo al thread por que me esta costando encontrar la
sugerencia a mi proyecto con tanta cosa de exception
dado que open devuelve una referencia a file, devolver a None seria
consistente
En mi opinión, tener que revisar si lo que te devolvió es None cada
vez que abrís un archivo (o exponerte a errores peores luego), es poco
pythónico.
Aparte, para saber porqué no lo pudo abrir, podríamos hacer que pusiera el
mensaje de error en una variable global. Pongamosle que se llame errno!
--
("\''/").__..-''"`-. . Roberto Alsina
`9_ 9 ) `-. ( ).`-._.`) KDE Developer (MFCH)
(_Y_.)' ._ ) `._`. " -.-' http://lateral.netmanagers.com.ar
_..`-'_..-_/ /-'_.' The 6,855th most popular site of Slovenia
(l)-'' ((i).' ((!.' according to alexa.com (27/5/2007)

Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it. --Brian W. Kernighan
John Rowland Lenton
2008-10-06 19:28:40 UTC
Permalink
Post by Roberto Alsina
Post by Facundo Batista
El día 6 de octubre de 2008 15:10, Juan B Cabral
Post by Juan B Cabral
Post by Facundo Batista
En tu opinión, ¿qué debería hacer open() si le pasás un archivo que no
existe?
cambiandole de titulo al thread por que me esta costando encontrar la
sugerencia a mi proyecto con tanta cosa de exception
dado que open devuelve una referencia a file, devolver a None seria
consistente
En mi opinión, tener que revisar si lo que te devolvió es None cada
vez que abrís un archivo (o exponerte a errores peores luego), es poco
pythónico.
Aparte, para saber porqué no lo pudo abrir, podríamos hacer que pusiera el
mensaje de error en una variable global. Pongamosle que se llame errno!
y devolver un objeto que supiera decirte todo eso, que se porte como
archivo, pero sin que sea una excepción, es demasiado loco?
Facundo Batista
2008-10-06 19:35:32 UTC
Permalink
El día 6 de octubre de 2008 16:28, John Rowland Lenton
Post by John Rowland Lenton
y devolver un objeto que supiera decirte todo eso, que se porte como
archivo, pero sin que sea una excepción, es demasiado loco?
Loco no, pero insufrible.

O sea, tendría que hacer algo como:

algo = open(...)
if algo.error_happened:
print "problema:", algo.error_description
else:
info = algo.read()

Slds.
--
. Facundo

Blog: http://www.taniquetil.com.ar/plog/
PyAr: http://www.python.org/ar/
Mariano Guerra
2008-10-06 19:41:00 UTC
Permalink
On Mon, Oct 6, 2008 at 5:35 PM, Facundo Batista
Post by Facundo Batista
El día 6 de octubre de 2008 16:28, John Rowland Lenton
Post by John Rowland Lenton
y devolver un objeto que supiera decirte todo eso, que se porte como
archivo, pero sin que sea una excepción, es demasiado loco?
Loco no, pero insufrible.
algo = open(...)
print "problema:", algo.error_description
info = algo.read()
El problema que veo en eso es que deberian todos de ponerse de acuerdo
en la forma de poner disponible la info de los errores, ademas tus
objetos deberian llevar atributos y metodos para handlear errores
(aunque podrian estar en object ;), ademas cambias un
try/except/finally por un if/elif/else, osea que muy lejos no estamos
yendo (a menos que me este perdiendo alguna ventaja)

PD: no estoy defendiendo las excepciones, pero me parece que al menos
es una solucion unificada.
Roberto Alsina
2008-10-06 19:15:54 UTC
Permalink
Post by Juan B Cabral
Post by Facundo Batista
El día 6 de octubre de 2008 15:46, Daniel F Moisset
Post by Daniel F Moisset
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?
Slds.
cambiandole de titulo al thread por que me esta costando encontrar la
sugerencia a mi proyecto con tanta cosa de exception
dado que open devuelve una referencia a file, devolver a None seria
consistente
Entonces cada vez hay que hacer

f=open('loquesea')
if not f:
#manejar el error

No podes hacer open('archivo').read() (da excepcion de que None no tiene
read())

No podes hacer

for l in open('archivo'): (da excepcion de que None no es iterable)

Ahora en vez de tener un IOError tenes 20 excepciones distintas, o que hacer
una cascada de ifs.

No gracias ;-)
--
("\''/").__..-''"`-. . Roberto Alsina
`9_ 9 ) `-. ( ).`-._.`) KDE Developer (MFCH)
(_Y_.)' ._ ) `._`. " -.-' http://lateral.netmanagers.com.ar
_..`-'_..-_/ /-'_.' The 6,855th most popular site of Slovenia
(l)-'' ((i).' ((!.' according to alexa.com (27/5/2007)

Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it. --Brian W. Kernighan
Daniel F Moisset
2008-10-06 20:09:17 UTC
Permalink
Post by Facundo Batista
El día 6 de octubre de 2008 15:46, Daniel F Moisset
Post by Daniel F Moisset
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
Mariano Guerra
2008-10-06 20:19:03 UTC
Permalink
Post by Daniel F Moisset
Post by Facundo Batista
El día 6 de octubre de 2008 15:46, Daniel F Moisset
Post by Daniel F Moisset
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
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é).
pense que era el unico que pensaba A) :D, en un proyecto nuevo, en
7000 lineas de codigo tengo 4 raises, y por ahi me parece raro
escribir tan pocos, pero lo que si noto es que no escondo ninguna
informacion de utilidad al usuario, no uso returns para devolver
informacion de error ni nada por el estilo, siempre uso algo asi como
el ejemplo que dio Daniel sobre los archivos.

por ahi el tema es que toda la app la escribo yo y lo hago de una
manera uniforme, habría que ver como seria si estuviera escribiendo un
modulo de la libreria estandar..
Daniel F Moisset
2008-10-07 21:47:58 UTC
Permalink
Post by Mariano Guerra
Post by Daniel F Moisset
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é).
pense que era el unico que pensaba A) :D, en un proyecto nuevo, en
7000 lineas de codigo tengo 4 raises, y por ahi me parece raro
escribir tan pocos, pero lo que si noto es que no escondo ninguna
informacion de utilidad al usuario, no uso returns para devolver
informacion de error ni nada por el estilo, siempre uso algo asi como
el ejemplo que dio Daniel sobre los archivos.
No sos el único... Ward Cunningham dice "exceptions are exceptional:
they should only be used for rare events, not for the normal control
flow".

Si 4 raises en 7000 líneas de código te parece ajustado, hay gente
acostumbrada a este estilo. Fijate la tabla en la página 33 de
http://homepages.cs.ncl.ac.uk/alexander.romanovsky/home.formal/EHOOS-report.pdf
para algunos ejemplitos: 13 raises en 372000 lineas de código, ó 0
raises en 115000. Eso laburando en un contexto donde en todas las capas
tenés la noción de "una excepción es algo catastrófico" (pero con
generación de excepciones cuando el developer mete la pata, no es que
sea programación en C)

En particular, si te interesa el tema, el informe ese tiene varios
papers de una conferencia, y un par de ellos estan buenos.

Saludos,
D.
Lucio Torre
2008-10-06 21:08:54 UTC
Permalink
Post by Daniel F Moisset
Mi favorita es la versión espartana/minimalista, basada en "una rutina
tiene que hacer una sola cosa y hacerla bien". Eso, llevado a diseño de
[snip]
Post by Daniel F Moisset
* La información esta es para debugging más que para control: Un fallo
quiere decir que se produjo una situación inesperada y muy desconocida.
Para manejar situaciones inusuales pero que son "esperadas" o
"conocidas" se usa el flujo de control usual (léase "if")
esto no se deriva de lo anterior. es decir, esto es por gusto tuyo.

yo diria que le cambiemos el nombre, en lugar de excepciones les
podriamos poner, nose, condiciones. (gracias roberto).

Lucio.
Daniel F Moisset
2008-10-07 22:10:12 UTC
Permalink
Post by Mariano Guerra
Post by Daniel F Moisset
Mi favorita es la versión espartana/minimalista, basada en "una rutina
tiene que hacer una sola cosa y hacerla bien". Eso, llevado a diseño de
[snip]
Post by Daniel F Moisset
* La información esta es para debugging más que para control: Un fallo
quiere decir que se produjo una situación inesperada y muy desconocida.
Para manejar situaciones inusuales pero que son "esperadas" o
"conocidas" se usa el flujo de control usual (léase "if")
esto no se deriva de lo anterior. es decir, esto es por gusto tuyo.
Todo es por gusto mío, desde "mi esquema favorito es..." en adelante :)

La derivación de lo anterior viene por este lado: Yo propuse usar
excepciones sólo para casos donde no queda otro y estas seguro que estás
mal. Entonces, el contexto de una excepción (a lo que me refiero con "la
información ésta" en el párrafo que dejaste) puede ser realmente
cualquier cosa. Tenés una alteración de flujo de control por ser un
fallo (en base a la distinción binaria de "devuelve un valor"/"falla"),
pero cual fallo es probablemente no te importe mucho; de hecho puede ser
tan cualquier cosa que no hay mucho código útil que puedas escribir en
base a eso, así que adelante.

Si era una condición esperada y detectable, por que sería una excepción.
Post by Mariano Guerra
yo diria que le cambiemos el nombre, en lugar de excepciones les
podriamos poner, nose, condiciones. (gracias roberto).
Como quieras... en muchos lenguajes se le llama excepciones a cosas con
semántica un poco distinta. Le dije excepciones a esto porque no me
pareció fuera del rango, y de hecho es con el mismo propósito para el
cual dicen que son los sistemas de excepciones (léase
"fault-tolerance").

Ahora, para la gente que cree que las excepciones son "fancy flow
control" ó "goto 2.0", sí, capaz le va a resultar muy distinto lo que yo
propongo.

Lo que yo propongo no es un mecanismo muy distinto al de Python o Java
(es casi un subconjunto); es más una propuesta metodológica de _cómo y
cuándo usar_ las excepciones. No creo que eso amerite un nombre
distinto.

Para mi (y de vuelta, sí, esto es gusto personal), deberías poder
escribir cualquier sistema sin ningún exception handler, y si sos un
programador perfecto, tenés infinita RAM, tu hardware no falla, y no
pasan eventos externos raros, debería andar todo correcto; las
excepciones manejan los problemas de que no somos perfectos, la RAM es
finita, el hardware se rompe, y suceden eventos externos al programa y
fuera de control que influyen en su comportamiento. Pero en Python (o en
Java, para el caso), para escribir un programa cuya especificación sea
"mostrá el contenido de tal archivo, ó 'hola mundo' si no existe", estoy
forzado a poner exceptions handlers.

Para mi, que open() levante un IOError por no poder abrir un archivo, es
igual de incómodo/impráctico que si el operador < levantara una
excepción NotBigEnoughException al preguntar a<2 con a=3 [1]. Seguro que
igual podríamos programar todo (usando try/catch en casos que ahora
usamos if/else), pero lo siento como un abuso del mecanismo.

Saludos,
D.

[1] Bueno, exagero un poquito en el ejemplo, pero creo que sólo porque
uso mas "<" que "open".

Juan BC
2008-10-03 23:19:11 UTC
Permalink
creo que se me paso eso de la exception... no fue aproposito... y si
toReturn va a quedar se :P

El 3 de octubre de 2008 18:29, Gabriel Genellina
Post by Juan B Cabral
Corregi mi proyecto dadas las sugerencias de los Igores[0] voluntarios
Post by Juan B Cabral
cuando el codigo tenga 0 criticas me dedicare a la documentacion y
distribucin (recordemos que aun estoy aprendiendo y le pongo pilas para
dejar el mejor producto posible)
1 - el tema de por que meto tanto la pata con los except son costumbres
java (ya se van a ir) de todas maneras dejo unos raise para algunos tipos de
exceptions que no se que no debo hacer nada.
Java tiene excepciones chequeadas (una metida de pata de diseño) y entonces
es re comun que haya que atrapar todas las excepciones que aparecen nada mas
para cambiarles el tipo. Eso para lo unico que sirve es para esconder
informacion valiosa (como cuál fue el verdadero error original), o induce a
try: ...
except: pass
que es como esconder el polvo abajo de la alfombra.
En Python la regla sería, parafraseando a mi abuela: "Si no tenes nada
bueno que hacer con la excepcion, sencillamente no la atrapes". Que siga su
curso, hasta que alguien más arriba con mas "contexto" la atrape y haga algo
útil.
toReturn = _get_hostname() + ":\n\t"
toReturn += _read_file()
toReturn += 'A name policy has not been defined.'
raise e
raise
return toReturn
El except: raise esta de mas, lo podes sacar y no pasa nada. O sea: una
clausula except que *solo* contiene un raise, es totalmente transparente,
como si no existiera; solo sirve para alargar el codigo en numero de lineas
y en tiempo de ejecucion.
El `raise e` de mas arriba, sí deberia ser un raise pelado. Tal como está
ahora, el error "nace" en la linea que dice `raise e`, y eso es lo que te
mostraria un traceback. Pero en realidad es anterior, el error saltó al
intentar abrir el archivo, y sería bueno que te lo muestre así. Para eso
usas `raise`, a secas, que lanza la ultima excepcion manteniendo el
traceback completo original.
Otra cosa es que esta mezclado en el script principal, si start() *imprime*
un texto o *devuelve* un texto (en caso de error, imprime y devuelve). En
general, diria que start() y _get_response tienen responsabilidades
mezcladas (podrías decir *que* hace cada una en una sola oracion?).
Y en general, yo prefiero que los errores se propaguen a traves de
excepciones, y no a traves del valor retornado por la funcion. O sea, si
set_whyname_string no puede hacer lo que se supone que tiene que hacer,
entonces lanza una excepcion; vos en su lugar estas devolviendo el texto
"You not have permisions to read: \n\t" + path
Por ejemplo,si el que invoco set_whyname_string quiere saber si anduvo bien
o no, es dificil, hay que andar mirando el texto devuelto a ver si tiene
pinta de error. Y si no lo verificas en el mismo lugar en que hiciste la
llamada, perdiste - se pierde esa informacion. Eso es lo bueno de usar
excepciones (el tratamiento del problema se difiere hasta el momento en que
alguien esta en condiciones de hacer algo util, no hace falta hacerlo en el
mismisimo lugar en que se detectó).
2 - mi costumbre de toReturn, toWrite... viene principalmente de una
Post by Juan B Cabral
confusion que tube con un profe de la facu. el tipo en su perra vida
identificaba la variable donde resolvia la funcion. Con eso dejo muy en
claro y nunca mas se confundio. A mi particularmente me resulta muy muy
comodo que si tengo un metodo "get_wawawa()" si adentro hay una var del tipo
"toReturn" es esa la variable donde se carga todo lo que se "debe" cargar...
es cuestion de gustos... a lo sumo la adaptare mas a lo python como
"to_return". pero simplementem me gusta
Ok, yo dentro de get_wawawa() usaria una variable llamada wawawa para ir
guardando lo que voy a devolver... pero si, es cuestion de gustos nomas. A
veces uso result, porque la mitad del tiempo programo en Delphi.
gracuas a los igores y se agradecen que "sigan bajando" la palanca para
Post by Juan B Cabral
ver si la critura vive.(osea sigan criticando)
Estoy criticón, se nota? Pero va con onda... :)
--
Gabriel Genellina
---------------------------------------------------------------------
PyAr - Python Argentina - Sitio web: http://www.python.com.ar/
--
Juan B Cabral
Loading...