Awsome Python - chained exceptions

Chris Angelico rosuav at gmail.com
Wed Feb 13 17:10:42 EST 2013


On Thu, Feb 14, 2013 at 3:14 AM, Rick Johnson
<rantingrickjohnson at gmail.com> wrote:
> On Wednesday, February 13, 2013 12:58:46 AM UTC-6, Chris Angelico wrote:
>> No, the offending (not offensive) line is "return items[index-1]",
>> which doesn't feature in your traceback at all.
>
> Do you realize that you are quoting DeAprano and not me? Whether you realize this fact or not, consider the next two questions.

I knew who I was quoting.

>   Q1: How could a line in the "try" block ever be considered
>   offensive? Because it throws an error? Are you serious?

You're the one who said offensive. I specifically corrected you to
"offending", which is the appropriate word in that situation.

>   Q2: Why would the line in the try block be shown as
>   a "feature" of the traceback when the whole intent of
>   exception handling is to hide the error in the try
>   block! If you want to raise the exception in the try block
>   then you place a naked raise statement in the exception
>   block, BUT THEN, why even wrap the code in a try/except
>   in the first damn place!?

You seriously need to get into the real world and do some actual
debugging work. Here, let me give you an example of what you might
come across in the real world:

1) The program doesn't exhibit the failure symptoms until it's been
running for a couple of days.
2) Sending the program a SIGHUP influences the symptoms in peculiar ways.
3) The main symptom visible is that something that ought to have 2-3
threads actually has several hundred.
4) Your boss is paranoid about security, so the script files on the
running nodes have all been minified - no comments, no linebreaks,
short variable names, etc.
5) The exact nature of the bug depends on the interactions of up to 12
computers, all running similar code but doing different tasks.

Now tell me, what's the first thing you do? There are many right
answers to this question, but most of them involve one thing: Get more
information. Turn on verbose logging, add a monitoring wrapper, insert
output statements in various places... and make sure your exception
tracebacks give ALL the information.

> Man, you and DeAprano must be cut from the same block; or more correctly, carved by the same shaky hand of a creator suffering the late-stage effects of Alzheimers disease.

D'Aprano (note, that's a 39 not a 101) and I both happen to have some
real-world experience. A bit of a rough teacher, and the tuition fees
are ridiculously high, but you learn things that aren't taught
anywhere else.

>> He is? Could just as easily be the print statement with a single
>> argument, with unnecessary parentheses around that argument. Which, if
>> I recall correctly, is one of the recommended approaches for making
>> 2/3 bi-compatible code.
>
> Really?
>
> Because if he did in-fact write the print statement using parenthesis (in some foolish attempt to make his code forward-compatible) that would mean i should add /another/ coding abomination to my earlier list of abominations. The proper method of using a forward compatible print function is by /importing/ the feature.
>
>    from future import print_function

>>> import __future__
>>> __future__.print_function
_Feature((2, 6, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 65536)

Which works back as far as 2.6 but that's all. Simply putting parens
around the argument works all the way back to... hmm. Further back
than I've ever had to support, but then, I only started using Python
seriously a few years ago. Steven?

>> No. Definitely not. Percent interpolation isn't going anywhere - core
>> devs have said so - and there are many occasions when it is at least
>> as well suited to the task as .format() is.
>
> In other words: Screw consistency and to hell with the zen?

Percent interpolation is plenty obvious, it's simple, it's clean, and
you're welcome to hate it if you like. Doesn't bother me.

> ...but what about when you need to substitute the /same/ substring in more than one location? Using the old nasty interpolation you are foced to write this:
>
>     print "Chris is a %s who is very %s-ish"%('troll', 'troll')
>
> ...ewwww yuck! String.format() to the rescue!
>
>     print "Chris is a {0} who is very {0}-ish".format('troll')

Yeah, in Pike I'd just use %<s to reuse the argument, or %[0]s to
explicitly set the index. If Python didn't have .format() and the
percent-haters like you, those features could easily be implemented.
If all you're doing is concatenating five strings, three of them
constants, there are plenty of other ways to do it; are you going to
start hating on str.format because you could use concatenation or
str.join()? Which is the one obvious way to do it?

So let's look at a more useful example. You need to tabulate some
data. For each line of output, you have a descriptive string, a
number, and a floating point value, and you want to output them like
this:

Normal           73     105.23
Disconnected     32      14.00
Shutting down     0       0.00
Busy              3    1333.33
Overloaded        1    1942.07

Your input is a list of lists or tuples with those three types: str,
int, float. You need to format them. Code golf mode, or maximum
clarity mode, up to you. Here are my options:

# Python, str.format()
for row in data:
    print("{:15s}{:4d}{:11.2f}".format(*row))

# Python, percent-formatting
for row in data:
    print("%-15s%4d%11.2f"%row)

//C++ - using a struct rather than a mixed array
for (record *row=data;row->desc;++row)
    printf("%-15s%4d%11.2f\n",row->desc,row->count,row->load);

//Pike, direct translation
foreach (data,array row)
    write("%-15s%4d%11.2f\n", at row);

//Pike, making use of array-output feature
write("%{%-15s%4d%11.2f\n%}",data);

Note how easily tabulated data can be produced, *across languages*,
with the exact same syntax. Actually, str.format borrows heavily from
printf notation, and I was able to make it look almost the same; all
it does is replace the percent sign with {:}. (Oh, and it defaults to
left-justifying strings, so I don't need the minus sign to do that.
Big deal.)

> (especially when they first claim consistency between languages and them expose that claim as a lie)

I think the comparison above shows my claim to be not a lie.

> [1] Read as: "I see that you are a lost cause". Hopefully you will grow a brain and read the format docs, and then try to apply it in your code, then MAYBE you will understand why i support str.format as the only method to format a string.

I've been working on that whole "growing a brain" thing, and I've
pretty much mastered it. My last troll almost grew one before he
committed suicide in shame. Would you like me to try the technique on
your body? It has a 90% chance of success.

> PS: Why do keep posting email addresses on the list? Does your client not trim, or at least warn, about these?

They're in the headers. What's the big deal? This is an email mailing
list, not just a newsgroup.

ChrisA



More information about the Python-list mailing list