With that said, let me at least offer a token defense of my position.
By way of motivation, I wrote that email after copying/pasting the
following a few times around a project until I wrote it into def
SilentlyDelete() and its cousin SilentlyRmdir()
""" code involving somefile """
try:
........os.remove(somefile)
except:
.......pass # The bloody search indexer has got the file and I
can't delete it. Nothing to be done.
Certainly the parade of horribles (bad files! corrupt data! syntax
errors!) is a tad melodramatic. Either os.remove() succeeds or it
doesn't and the execution path (in the estimation of this programmer,
at least) is not at all impacted by whether it succeeds or fails. I
know with certainty at compile time what exceptions might be raised
and what the consequences of passing them are and there is no sense
pestering the user or sweating over it. Nor can I see the logic, as
was suggested, in writing "except OSError:" since (seems to me) mere
surplusage -- it neither causes a semantic difference in the way the
program runs nor provides anything useful to the reader.
Now, perhaps this is a special case that is not nearly special enough
to warrant its own syntactic sugar, I granted that much, but >30,000
examples in Google Code cannot be considered to be a complete corner
case either. Briefly skimming those results, most of them seem to be
of this flavor, not the insane programmer that wants to write
"silence: CommitDBChangesEmailWifeAndAdjustBankAccount()" nor novices
that aren't aware of what they might be ignoring.
At any rate (and since this is far more words than I had intended), I
want to reiterate that the criticism is well-taken as a cultural
matter. I just don't want everyone to think I'm bloody insane or that
I'm not aware this is playing with fire. Maybe we can put it in module
"YesImSureJustBloodyDoItAlreadyGoddamnit" and prints an ASCII skull
and crossbones to the console when imported? :-P
~ Oren
PS. I did like Dave's suggestions that one might want to write
"silence Type1 Type2:" which I suppose goes a long way towards
alleviating the concern that the programmer doesn't know what he's
missing. Doesn't quite meet my desire (both syntaxes would be nice, of
course) to avoid the verbiage involved with explaining to the compiler
(or the next reader) something that it knows well enough by now (or
ought to know, at least).
You just found the right solution: define a function for something
that you do repeatedly. No need to change the language.
Cheers,
Daniel
--
Psss, psss, put it down! - http://www.cafepress.com/putitdown
I admit there are times I've done something similar, usually with
what I call my "int0" and "float0" utility functions which
roughly translate to "give me a stinkin' int/float and if
something goes wrong, give me 0, but the return result better
darn well be an int/float!" functions. But as you describe and
was later commended as a right-ish way to approach it,
abstracting that off into a function with minimal code in the
try: block is the right way to go.
-tkc
def int0(v):
"""converts v to a int, or returns 0 if it can't"""
try:
return int(v)
except: # usually a ValueError but catch all cases
try:
# int("1.1") fails so try float()ing it first
return int(round(float(v)))
except:
return 0
def float0(v):
"""converts v to a float, or returns 0 if it can't"""
try:
return float(v)
except:
return 0.0
You don't know that what you stated in your comment is true.
All you know is that there was an exception. To find the reason, you
have to inspect the exception.
You escpecially do NOT know whether the file is removed or not.
OK, os.remove() might be a CPython builtin (not sure ATM), but in
general all sort of crazy things can happen here, like ImportError
raised by code in the lib or so.
And of course: a bare except: also catches ^C or SystemExit. That is
almost certainly *not* what you want, right?
To your first question about a "silenced" keyword: you could emulate
this with context managers I guess.
Something like (untested, just a quick mockup how it could look):
class silenced:
def __init__(self, *silenced):
self.exceptions=tuple(silenced) #just to be explicit
def __enter__(self):
return self #dito1
def __exit__(self, type, value, traceback):
for ex in self.exceptions:
if isinstance(value, ex):
return True #supresses exception
So:
with silenced(os.Error):
os.remove(somefile)
Would translate to:
try:
os.remove(somefile)
except os.Error:
pass
One nice thing about this approach would be that you can alias a set of
exceptions with this:
idontcareabouttheseerrors=silenced(TypeError, ValueError, PEBCAKError,
SyntaxError, EndOfWorldError, 1D10T_Error)
with idontcareabouttheseerrors:
do_stuff()
Regards,
Michael
I think replacing `except:` with `except StandardError:` would work as well,
and be correct, too.
Mel.
> With that said, let me at least offer a token defense of my position. By
> way of motivation, I wrote that email after copying/pasting the
> following a few times around a project until I wrote it into def
> SilentlyDelete() and its cousin SilentlyRmdir()
>
> """ code involving somefile """
> try:
> ........os.remove(somefile)
> except:
> .......pass # The bloody search indexer has got the file and I can't
> delete it. Nothing to be done.
Or:
(1) you forgot to import the os module
(2) the os module (or os.remove) was rebound or monkey-patched to
something unexpected
(3) you have a bug in your code and somefile=23 (say) instead of the
filename you're expecting
(4) the user hit the interrupt key just at that instance
(5) somefile doesn't exist
(6) somefile does exist, but you don't have write-permission for it
(7) the disk is mounted read-only
(8) you don't have a search indexer and something else has gone wrong
Hiding all those different errors is, quite frankly, shoddy work.
#1-3 certainly shouldn't be hidden, as they are bugs in your program. #4
shouldn't be hidden, ignoring the user's interrupt command is bad, and
rude if it is deliberate. #5 probably shouldn't be hidden either, as it
most likely indicates a program bug, but some rare applications may be
okay with ignoring it. And #6-8 should be told to the user, so they can
fix the problem.
--
Steven
> With that said, let me at least offer a token defense of my position.
> By way of motivation, I wrote that email after copying/pasting the
> following a few times around a project until I wrote it into def
> SilentlyDelete() and its cousin SilentlyRmdir()
>
> """ code involving somefile """
> try:
> ........os.remove(somefile)
> except:
> .......pass # The bloody search indexer has got the file and I
> can't delete it. Nothing to be done.
>
> Certainly the parade of horribles (bad files! corrupt data! syntax
> errors!) is a tad melodramatic. Either os.remove() succeeds or it
> doesn't and the execution path (in the estimation of this programmer,
> at least) is not at all impacted by whether it succeeds or fails. I
> know with certainty at compile time what exceptions might be raised
> and what the consequences of passing them are and there is no sense
> pestering the user or sweating over it. Nor can I see the logic, as
> was suggested, in writing "except OSError:" since (seems to me) mere
> surplusage -- it neither causes a semantic difference in the way the
> program runs nor provides anything useful to the reader.
Suppose you misspell 'somefile' or 'remove' (or the file gets corrupted
somehow -- which unfortunate can happen). Now you suppress the NameError
or AttributeError, which is a mistake. Suppose someone copies your code
into a context where 'os' is not imported or where 'os' is a variable
(for bone type, for instance). More bad error suppression.
Bare excepts seem ok for experimental, draft, or throwaway code, but
somewhat dubious for production code.
For anyone reading your code a few years from now, 'except OSError'
would be clearer that that is all you mean to pass on.
Wrapping the code in a function makes the overhead of adding 'OSError'
trivial. It also makes it trivial to do something different, like adding
the file to a collection to be retried later. It also reduces the points
of possible corruption to one instead of many.
Terry Jan Reedy