Hidden string formatting bug

Tim Peters tim.peters at gmail.com
Thu Oct 13 22:05:45 EDT 2005


[Echo]
> I have been trying to figure out the problem with this string formatting:

[monstrous statement snipped]

> when it executes, I get this error: "inv argument required".

That shoud be "int", not "inv".

> I have checked and rechecked both the string and the tuple. I cant figure
> out what the problem is.  After playing around with it, i found out if change
> the last line to: "%s,%i) %(... I get a different error. The error is "not all
> arguments converted during string formatting".
>
> So I am baffled and confused as of why this wont work. Is anyone able to
> shed some light on my hidden bug?

Yup, it's precedence.  Here's the same thing:

sql = "%s" + \
      "%i" % ("abc", 2)

Run that and you get "int argument required".  Change the last %i to
%s and you get "not all arguments converted during string formatting".
 Both error messages are accurate.

That's because % binds tighter than "+".  As a 1-liner, and inserting
redundant parentheses to make the precedence obvious, my simplified
example is

sql = "%s" + ("%i" % ("abc", 2))

What you intended _requires_ inserting more parentheses to force the
intended order (if you're going to stick to this confusing coding
style):

sql = ("%s" + "%i") % ("abc", 2)

Better is to not use "+" on string literals, and not use backslash
continuation either; try this instead:

sql_format = ('string1'
                    'string2'
                    'string3'
                    ...
                    'last string')

Build the format in a separate statement to reduce the chance of
errors (for example, your original mistake would have been impossible
to make this way).  Use parens instead of backslashes.  Don't use "+"
to catenate string literals:  the Python compiler automatically
catenates adjacent string literals for you, and at compile-time (so
it's even more efficient than using '"+").



More information about the Python-list mailing list