Why not allow empty code blocks?

Steven D'Aprano steve at pearwood.info
Fri Jul 29 23:49:49 EDT 2016


On Sat, 30 Jul 2016 04:32 am, Antoon Pardon wrote:

> Op 29-07-16 om 16:38 schreef Steven D'Aprano:
>> On Fri, 29 Jul 2016 11:55 pm, Antoon Pardon wrote:
>> 
>>> Op 29-07-16 om 15:43 schreef Steven D'Aprano:
>>>> Of course it won't, which is why I don't believe all these folks who
>>>> claim that they regularly ("all the time", "fairly often") replace
>>>> except blocks with `pass`. I call shenanigans -- perhaps you do it
>>>> *occasionally*, but as a general rule, you can rarely replace the
>>>> exception handler with a do-nothing clause and expect your code to
>>>> work:
>>>>
>>>> try:
>>>>     block
>>>> except SomeException:
>>>>     handle error
>>>> process
>>>>
>>>> If you remove the error handling block, replacing it with `pass`, in
>>>> general your code will just break again as soon as it continues
>>>> processing.
>>>
>>> I think the case where you just want to ignore the exception, but it can
>>> at times be useful to get some extra logging information for debuging
>>> purposes, is not that rare as you seem to suggest.
>> 
>> I think I can count the number of times I've wanted to ignore an
>> exception on the fingers of one hand. And when I did, there was no need
>> to debug it, because I only ignore expected failures. There's nothing to
>> debug.
> 
> You really should stop, generalising your own situation.

I'm not just generalising from code I've written. I'm generalising from code
I've reviewed, code I've read, code I've seen others admire, code I've seen
others mock and laugh at, and best practices I've read about. That's
called "learning to be a better programmer".


>> But even if you do it all the time, how do you "get some extra logging
>> information" by replacing the "except" block with `pass`? If you replaced
>> the "except" block with a call to the logger, that would be one thing.
>> But "pass", that won't do the job.
> 
> You don't seem to understand. There is no real except block to be replaced
> by pass. There is sometime an except block added (or uncommented) to get
> logging information.

Perhaps its *you* who doesn't understand. The subject line talks
about "empty code blocks", and Bart has suggested that instead of having to
write


try:
    something
except SomeException:
    pass
process


(which he considers far too difficult) we should allow empty code blocks:


try:
    something
except SomeException:
process


because apparently saving that one indented line with "pass" makes all the
difference in language usability. That lead to Chris asking how common it
was to do this. That's when Bart said that he frequently *replaced* an
existing except block with "pass":


# before
try:
    something
except SomeException:
    handle error
    handle it some more
process

# after
try:
    something
except SomeException:
    pass
process


At which point *you agreed with him*:

[quote]
As BartC already mentions it happens fairly often during debugging.
Something like.

try:
   Some code
except Some_Exception:
   # Commented code for when I am debugging <Some code>
   pass
[end quote]



So now you're changing your story, and claiming that you're not actually
replacing an existing except block with pass (because I think any
experienced Python developer, which Bart is not, realises that's not likely
to work). Now you've got a use-case where we start with:

# before
some code
more processing

and add an entire try...except around it:

# step 1
try:
    some code
except SomeException:
    debugging code
more processing

*and then* comment out the debugging code and replace it with pass:

# after, as stated by you
try:
    some code
except SomeException:
    # debugging code
    pass
more processing


Of course it's legitimate to wrap some failing code in a temporary
try...except block for debugging purposes. But that's not an empty code
block, and its not "pass", and it's not relevant to Chris' question.

And what happens once you have finished debugging the code? According to
your post, you comment out the debugging code, replacing it by "pass". And
you do this *frequently*.

Okay, if you say you do that, I have to believe you. If we take you at your
word, then we can only conclude that your code is littered with the
detritus of old debugging code and unnecessary try...except blocks which do
nothing. That's practically the definition of *poor programming*, leaving
old code commented out to rot, but if you say that's what you do, who am I
to argue that you don't?

Since I don't actually believe you are that poor a programmer, I suspect
that what you actually do is not replace the debugging code with "pass",
like you claim, but that once you have finished debugging that section of
the code you remove the unneeded try...except block and dead, unused
debugging code, returning it to the "before" state.

D'Arcy's suggestion of leaving the debugging code in with a runtime switch
to turn it on and off also makes sense. I'm partial to switching on the
special __debug__ global. But we're getting further and further away from
Bart's scenario, of a bare "pass". *That's* what I don't believe in: this
supposed scenario where people have existing code blocks that they have to
replace with "pass", and that happens *frequently enough to matter*.

And of course as D'Arcy has pointed out, these two are not the same:

# before
some code

# after
try:
    some code
except SomeException:
    pass

To make the second one equivalent to the first, one should use *raise*, not
pass. In which case you could even leave your debugging code in there,
uncommented out:

try:
    some code
except SomeException:
    raise
    debugging code


all the better to confuse those who have to maintain the program in your
absence.



-- 
Steven
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.




More information about the Python-list mailing list