17

When formatting a string, my string may contain a modulo "%" that I do not wish to have converted. I can escape the string and change each "%" to "%%" as a workaround.

e.g.,

'Day old bread, 50%% sale %s' % 'today!'  

output:

'Day old bread, 50% sale today'

But are there any alternatives to escaping? I was hoping that using a dict would make it so Python would ignore any non-keyword conversions.
e.g.,

'Day old bread, 50% sale %(when)s' % {'when': 'today'}  

but Python still sees the first modulo % and gives a:

TypeError: not enough arguments for format string
sobolevn
  • 16,714
  • 6
  • 62
  • 60
Stephen Gornick
  • 173
  • 1
  • 1
  • 4

4 Answers4

24

You could (and should) use the new string .format() method (if you have Python 2.6 or higher) instead:

"Day old bread, 50% sale {0}".format("today")

The manual can be found here.

The docs also say that the old % formatting will eventually be removed from the language, although that will surely take some time. The new formatting methods are way more powerful, so that's a Good Thing.

Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
  • Unless you want to print "{{0}} = {0}".format("today"), then you won't like doubling up the curly braces. :^) – Mark Tolonen May 18 '10 at 01:27
  • @MarkTolonen Ugg, I specifically came here hoping to find a solution to the "{{0}}".format(...) problem... – KSletmoe Aug 02 '13 at 01:13
2

You can use regular expressions to replace % by %% where % is not followed by (

def format_with_dict(str, dictionary):
    str = re.sub(r"%([^\(])", r"%%\1", str)
    str = re.sub(r"%$", r"%%", str)  # There was a % at the end?
    return str % dictionary

This way:

print format_with_dict('Day old bread, 50% sale %(when)s', {'when': 'today'})

Will output:

Day old bread, 50% sale today

This method is useful to avoid "not enough arguments for format string" errors.

cfillol
  • 540
  • 4
  • 8
2

Not really - escaping your % signs is the price you pay for using string formatting. You could use string concatenation instead: 'Day old bread, 50% sale ' + whichday if that helps...

psmears
  • 26,070
  • 4
  • 40
  • 48
2

Escaping a '%' as '%%' is not a workaround. If you use String formatting that is the way to represent a '%' sign. If you don't want that, you can always do something like:

print "Day old bread, 50% sale " + "today"

e.g. not using formatting.

Please note that when using string concatenation, be sure that the variable is a string (and not e.g. None) or use str(varName). Otherwise you get something like 'Can't concatenate str and NoneType'.

extraneon
  • 23,575
  • 2
  • 47
  • 51