Do not use the 'try except' clause when 'if then' can perfectly handle
the case.
i.e.
try:
fromForm, junk = string.split(fromForm, ':')
except:
pass # This is only an expedient to split options that
have a colon in them, such as the colors
would be better written
# This is only an expedient to split options that have a colon in them,
such as the colors
if ':' in fromForm:
fromForm, junk = fromForm.split(':')
or
fromForm = fromForm.split(':')[0]
Anyway, you should definitely use a coding rule checker, like pylint or
pyckeck. It would sometimes point you into the correct direction. For
instance, pylint will tell you that except: pass is often (not always) a
clue for bad design/pattern and issue warnings for it.
In a more general manner, use try blocks when the code can throw
exceptions upon condition you do not control. When you know about the
conditions, use the if statement.
No:
a = None
try:
a.split()
except AttributeError:
pass
Yes:
a = None
if a:
a.split()
Exception are required in the following example:
try:
main()
except KeyboardInterrupt:
print 'interrupted by user'
Cheers,
JM
Rule N�2:
dont use BARE EXCEPT, or you'll piss off MRAB for good :o). Beside from
kidding, don't use bare except.
id = form.getfirst('id')
sql = 'update %s set ProdID="%s" Quantity="%s" %s where ID="%s";' %
(tmpTable, prodid, quantity, sqlUpdateMiddle, id)
try:
cursor.execute(sql)
db.commit()
except NAME_OF_THE_EXCEPTION :
raise # reraising without doing anything else is meaninless, you
could remove the try block
In your example you must lookt at your sql module documentation to know
which kind of exception it can throw.
JM
> Rule N°2:
> dont use BARE EXCEPT, or you'll piss off MRAB for good :o). Beside from
> kidding, don't use bare except.
I inherited some code that used bare excepts *everywhere*. There were
about 4K lines of code, IIRC, and I think that they were more except
clauses than elses. Eventually, I used sed to add a print_exc() after
each one, just so I could figure out what the expected exceptions
were. It was so bad that I seriously considered writing a program
just to parse all the tracebacks from my instrumented version and then
revise the source code for me, but I didn't want to accidentally miss
any "real" errors.
regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
PyCon is coming! Atlanta, Feb 2010 http://us.pycon.org/
Holden Web LLC http://www.holdenweb.com/
UPCOMING EVENTS: http://holdenweb.eventbrite.com/
> I inherited some code that used bare excepts *everywhere*. There were
> about 4K lines of code, IIRC, and I think that they were more except
> clauses than elses.
Visual Basic programmers will learn how to write “ON ERROR RESUME NEXT”
<URL:http://www.vbinfozine.com/a_onerror.shtml> in any language put
before them.
--
\ “I'm a born-again atheist.” —Gore Vidal |
`\ |
_o__) |
Ben Finney
Happy new year,
Dimitris Leventeas
> Why we should prefer ``if: ...'' over a ``try: ... except something:
> pass'' block?
We shouldn't, not in general.
Often, the if test is just as expensive as actually doing it. E.g.:
if x in mylist:
position = mylist.index(x)
else:
do_something()
has to search the list twice, first to see if x is there, then search it
again to return the index. That does double the work needed. A better way
is:
try:
position = mylist.index(x)
except ValueError:
do_something()
unless you expect that x is often missing: setting up the try block is
much faster than the test, but catching the exception is much, much
slower. So long as exceptions are rare, it is better to use the try
version (also known as "Better to ask forgiveness than permission"). But
if exceptions are common, it may be better to use the if version ("Look
before you leap").
The try version is also better whenever there could be a race condition.
For example, when opening a file, you might be tempted to do this:
if os.path.exists(filename):
f = open(filename, 'r')
text = f.read()
else:
print "file missing"
but that is dangerous in a multi-processing computer system (which nearly
all computers are these days). The problem is that in the fraction of a
second after you test that the file exists, some other process might come
along and delete it and the open call will then fail. So to be safe, you
have to do this:
if os.path.exists(filename):
try:
f = open(filename, 'r')
except IOError:
print "file missing"
else:
text = f.read()
else:
print "file missing"
But of course now the test is redundant, and all you really need is the
try...except block:
try:
f = open(filename, 'r')
except IOError:
print "file missing"
else:
text = f.read()
(Note: the above is still not entirely robust. For example, if you try to
read a file that you don't have permission to read, it wrongly reports it
is missing instead of a permissions error. To make this more robust, you
need to inspect the exception and check the error code.)
--
Steven
One exception (pun intended) is if the try-block have a side effect that
is difficult to cleanup cleanly.
OTOH, if you want to do something different depending on whether the file
exists, you need to use both approaches:
if os.path.exists(fname):
try:
f = open(fname, 'rb')
data = f.read()
f.close()
return data
except IOError:
logger.error("Can't read: %s", fname)
return ''
else:
try:
f = open(fname, 'wb')
f.write(data)
f.close()
except IOError:
logger.error("Can't write: %s", fname)
return None
(This is a somewhat stupid example strictly for illustration. A better
and more-elaborate example would be something like trying to copy a file
to fname and rename an existing file to '.bak' if it exists. The tricky
part would be trying to rename the '.bak' to fname if the copy fails.
And yes, that's exactly what some code I wrote a few days ago does.)
--
Aahz (aa...@pythoncraft.com) <*> http://www.pythoncraft.com/
Weinberg's Second Law: If builders built buildings the way programmers wrote
programs, then the first woodpecker that came along would destroy civilization.
> OTOH, if you want to do something different depending on whether the
> file exists, you need to use both approaches:
>
> if os.path.exists(fname):
> try:
> f = open(fname, 'rb')
> data = f.read()
> f.close()
> return data
> except IOError:
> logger.error("Can't read: %s", fname) return ''
> else:
> try:
> f = open(fname, 'wb')
> f.write(data)
> f.close()
> except IOError:
> logger.error("Can't write: %s", fname)
> return None
Unfortunately, this is still vulnerable to the same sort of race
condition I spoke about.
Even more unfortunately, I don't know that there is any fool-proof way of
avoiding such race conditions in general. Particularly the problem of
"open this file for writing only if it doesn't already exist".
> (This is a somewhat stupid example strictly for illustration. A better
> and more-elaborate example would be something like trying to copy a file
> to fname and rename an existing file to '.bak' if it exists. The tricky
> part would be trying to rename the '.bak' to fname if the copy fails.
> And yes, that's exactly what some code I wrote a few days ago does.)
Sounds interesting and useful. Would you care to share it with us, or to
publish it as a recipe?
--
Steven
What if the "if ..." test has a side-effect? This is an argument against
side-effects, not against using exceptions.
But of course you are right, there are lots of good reasons for choosing
to use an if test rather than a try block, or vice versa. I would argue
that the try block is generally more Pythonic, and should be preferred,
but that doesn't mean that there aren't reasons for sometimes choosing
other strategies instead.
--
Steven
It's atomic, and fails politely if the file already exists.
No idea if Unix has a similar functionality.
DaveA
True; nevertheless, my point remains that if you want to do something
different depending on whether the file exists, you must use both LBYL
and EAFP.
>Even more unfortunately, I don't know that there is any fool-proof way of
>avoiding such race conditions in general. Particularly the problem of
>"open this file for writing only if it doesn't already exist".
IIUC, you can lock files that don't exist.
>> (This is a somewhat stupid example strictly for illustration. A better
>> and more-elaborate example would be something like trying to copy a file
>> to fname and rename an existing file to '.bak' if it exists. The tricky
>> part would be trying to rename the '.bak' to fname if the copy fails.
>> And yes, that's exactly what some code I wrote a few days ago does.)
>
>Sounds interesting and useful. Would you care to share it with us, or to
>publish it as a recipe?
Unfortunately, it's a bit too tightly tied to some other stuff in the
code, plus I'll need to get permission from my bosses. We'll see.
--
Aahz (aa...@pythoncraft.com) <*> http://www.pythoncraft.com/
"If you think it's expensive to hire a professional to do the job, wait
until you hire an amateur." --Red Adair
It does. In Unix, you'd pass O_CREAT|O_EXCL to the open(2) system
call (O_CREAT means create a new file, O_EXCL means exclusive mode:
fail if the file exists already).
The python os.open interface looks suspiciously like the Unix system
call as far as invocation goes, but it wraps the Windows functionality
properly for the relevant flags. The following should basically work
on both OSes (though you'd want to specify a Windows filename, and
also set os.O_BINARY or os.O_TEXT as needed on Windows):
import os
def exclusive_open(fname):
rv = os.open(fname, os.O_RDWR|os.O_CREAT|os.O_EXCL)
return os.fdopen(rv)
first = exclusive_open("/tmp/test")
print "SUCCESS: ", first
second = exclusive_open("/tmp/test")
print "SUCCESS: ", second
Run that and you should get:
SUCCESS <open file '<fdopen>', mode 'r' at 0xb7f72c38>
Traceback (most recent call last):
File "testopen.py", line 9, in <module>
second = exclusive_open("/tmp/test")
File "testopen.py", line 4, in exclusive_open
rv = os.open(fname, os.O_RDWR|os.O_CREAT|os.O_EXCL)
OSError: [Errno 17] File exists: '/tmp/test'
Thanks!
--
Aahz (aa...@pythoncraft.com) <*> http://www.pythoncraft.com/
import antigravity