401

I have the following code

test = "have it break."
selectiveEscape = "Print percent % in sentence and not %s" % test

print(selectiveEscape)

I would like to get the output:

Print percent % in sentence and not have it break.

What actually happens:

    selectiveEscape = "Use percent % in sentence and not %s" % test
TypeError: %d format: a number is required, not str
Martin Thoma
  • 91,837
  • 114
  • 489
  • 768
jondykeman
  • 5,632
  • 3
  • 19
  • 20
  • @KarlKnechtel: But I have personally met the problem when the formatting template was read from a file. If you have no control over what is inside the file, then the question is legitimate. – pepr May 22 '12 at 07:22
  • If the formatting template is in a file, then getting the template correct - including proper escaping of `%` symbols - is the responsibility of the file creator. – Karl Knechtel May 22 '12 at 16:04
  • 70
    Why isn't it `\%`? That was my guess, I'm surprised to find it's `%%` instead - seems pretty counterintuitive. – Demis Apr 28 '15 at 16:14
  • 4
    `% i` means "a decimal representation of an integer, padded left with spaces. – Antti Haapala Apr 02 '16 at 21:19
  • 5
    The escape is to the function, not the language syntax. Hence if the escape was `\%` it would actually be `\\%` when written in ordinary code. `` is the typical pattern I've seen, and ``\`` happens to be the most common escape character, for better or worse. – shemnon Oct 14 '16 at 21:00
  • 1
    @Demis and how do you escape `\ ` if you had to print `\\%`? You are bound to require escaping through repetition of special characters, if the special characters are also not special depending on circumstances. – Sassa NF Jan 17 '17 at 21:48
  • 2
    I think it is annoying in Python that the the literal % is encoded by "%%" and not by "\%". – MasterControlProgram Nov 01 '17 at 18:39
  • @Ralf I find it more confusing that when I need to escape `%` in LaTeX mode, `r'\%'` doesn't work but `r'\%%'` works – nish-ant Dec 19 '19 at 16:12

6 Answers6

682
>>> test = "have it break."
>>> selectiveEscape = "Print percent %% in sentence and not %s" % test
>>> print selectiveEscape
Print percent % in sentence and not have it break.
Nolen Royalty
  • 16,989
  • 4
  • 37
  • 46
  • 48
    In Python 3.3.5, `print('%s%%' % 100)` prints `100%`. But `print('%%')` prints `%%`. So it looks like you don't have to escape the % signs if you don't make substitutions. – Zenadix Sep 08 '15 at 19:39
  • 5
    @Zenadix This is true in Python 2.7 as well – Tom Dec 15 '15 at 18:17
  • 2
    Note that the `%` method is actually deprecated (in Python 3) in favor of `str.format()`: https://docs.python.org/2/library/stdtypes.html#str.format – dantiston Feb 20 '17 at 18:45
  • 9
    Note that the `%` method is not depreciated in Python 3.6. It will continue to be supported in lieu of its similarity to c, c++, etc. `str.format()` and f-strings are preferred but not enforced. – Aaron Apr 07 '17 at 21:02
  • Just noticed that If the string is a json string, being read from a file you don't even need to escape the `%` sign. Just `%` will do – wander95 Dec 19 '17 at 16:24
  • You can also be sneaky and do `print "Print percent %" + "variable %s" % 'text'` as a dirty workaround. – dragon788 Dec 31 '18 at 23:35
60

Alternatively, as of Python 2.6, you can use new string formatting (described in PEP 3101):

'Print percent % in sentence and not {0}'.format(test)

which is especially handy as your strings get more complicated.

Karmel
  • 3,382
  • 2
  • 15
  • 11
43

try using %% to print % sign .

Botz3000
  • 37,236
  • 8
  • 100
  • 125
openmeet123
  • 469
  • 3
  • 2
8

You can't selectively escape %, as % always has a special meaning depending on the following character.

In the documentation of Python, at the bottem of the second table in that section, it states:

'%'        No argument is converted, results in a '%' character in the result.

Therefore you should use:

selectiveEscape = "Print percent %% in sentence and not %s" % (test, )

(please note the expicit change to tuple as argument to %)

Without knowing about the above, I would have done:

selectiveEscape = "Print percent %s in sentence and not %s" % ('%', test)

with the knowledge you obviously already had.

Anthon
  • 51,019
  • 25
  • 150
  • 211
3

If the formatting template was read from a file, and you cannot ensure the content doubles the percent sign, then you probably have to detect the percent character and decide programmatically whether it is the start of a placeholder or not. Then the parser should also recognize sequences like %d (and other letters that can be used), but also %(xxx)s etc.

Similar problem can be observed with the new formats -- the text can contain curly braces.

pepr
  • 18,012
  • 11
  • 66
  • 122
2

If you are using Python 3.6 or newer, you can use f-string:

>>> test = "have it break."
>>> selectiveEscape = f"Print percent % in sentence and not {test}"
>>> print(selectiveEscape)
... Print percent % in sentence and not have it break.
Jaroslav Bezděk
  • 2,697
  • 2
  • 14
  • 29