Python
String Formatting
Escape Character
Percent Sign
Programming Tips

How can I selectively escape percent in Python strings?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

The percent sign (%) plays a special role in several Python string-formatting mechanisms. When you actually want a literal % in your output, you need to know which escape sequence to use for the formatting method you have chosen. This article covers every major approach: the legacy % operator, str.format(), f-strings, and string.Template, so you can confidently include percent signs wherever you need them.

The Legacy % Operator

The oldest formatting style in Python uses % as its interpolation marker, which means a bare % followed by a conversion character (like s, d, or f) is interpreted as a placeholder. To produce a literal percent sign you double it: %%.

python
1# Without escaping — raises TypeError
2# msg = "Disk usage: %d% full" % 85
3
4# Correct: use %% to get a literal %
5msg = "Disk usage: %d%% full" % 85
6print(msg)  # Disk usage: 85% full

The %% escape only applies inside strings that are actually being formatted with the % operator. In a plain string that is never passed through %, a single % is perfectly fine.

python
plain = "100% complete"  # no formatting, no error
print(plain)             # 100% complete

This distinction trips up many beginners: the percent sign is only special when the string is used as the left operand of %.

str.format() and Literal Braces

Starting with Python 2.6, str.format() replaced % as the recommended formatting tool. Here the special characters are { and }. A literal percent sign needs no escaping at all, but if you want a literal brace you double it.

python
1# Literal % — no escaping needed
2print("Success rate: {:.1f}%".format(99.5))
3# Success rate: 99.5%
4
5# Literal braces — double them
6print("Set notation: {{1, 2, 3}}".format())
7# Set notation: {1, 2, 3}

A common mistake is to assume you still need %% when using str.format(). You do not. The only characters that require doubling in this system are { and }.

f-strings and Literal Braces

f-strings (available since Python 3.6) use the same brace-based syntax as str.format(). A literal % is written as-is, and a literal brace is doubled.

python
1usage = 85
2# Literal % — just type it
3print(f"Disk usage: {usage}%")
4# Disk usage: 85%
5
6# Literal braces
7print(f"The set is {{{1, 2, 3}}}")
8# The set is {1, 2, 3}

Inside the expression portion (between { and }), you can use any valid Python expression, but the text outside the braces is plain text where % carries no special meaning.

string.Template (Dollar-sign Substitution)

Python's string.Template class uses $ as its marker. Neither % nor {} need escaping. If you need a literal dollar sign, write $$.

python
1from string import Template
2
3t = Template("Tax rate: $rate% — cost: $$${price}")
4print(t.substitute(rate=8.5, price=50))
5# Tax rate: 8.5% — cost: $50

Template is handy when your string contains many braces or percent signs and you want to minimize escaping noise.

Mixing Formatting Methods Safely

Sometimes legacy code mixes % formatting with strings that contain literal percent signs and braces. The safest strategy is to pick one formatting method per string and stick with it. Here is a side-by-side comparison.

python
1name = "backup"
2pct = 73
3
4# % operator — escape % with %%
5msg1 = "Task '%s' is %d%% done" % (name, pct)
6
7# str.format — no % escaping needed
8msg2 = "Task '{}' is {}% done".format(name, pct)
9
10# f-string — no % escaping needed
11msg3 = f"Task '{name}' is {pct}% done"
12
13# All three produce: Task 'backup' is 73% done

Notice that the % operator version requires both the %% escape and careful ordering of conversion specifiers, while str.format() and f-strings let you write % directly.

Raw Strings and Percent Signs

Raw strings (r"...") suppress backslash escape processing, but they have no effect on % or brace interpretation. A raw string passed through the % operator still needs %%.

python
1path = r"C:\Users\admin"
2# raw string + % formatting — still need %%
3msg = r"Path: %s is 100%% valid" % path
4print(msg)  # Path: C:\Users\admin is 100% valid

Raw strings are useful for Windows file paths and regular expressions, but they do not change how the % operator or str.format() work.

Common Pitfalls

  • Using %% inside an f-string: f-strings do not interpret % specially, so %% will appear literally as two percent signs in the output instead of one.
  • Forgetting %% in logging format strings: The logging module uses %-style formatting internally. A call like logging.info("CPU at %d%", 90) will fail; you need logging.info("CPU at %d%%", 90).
  • Doubling braces when using % formatting: {{ and }} are only meaningful for str.format() and f-strings. In %-formatted strings, doubled braces appear literally as {{.
  • Mixing formatting styles in one string: Writing f"Score: %d%%" % 100 is a syntax error because Python treats the string as an f-string and never applies the % operator. Choose one method per string.
  • Assuming string.Template needs %%: Template.substitute() ignores % entirely. Writing %% will produce two percent signs in the output.

Summary

  • Use %% to produce a literal % only when formatting with the % operator or the logging module.
  • In str.format() and f-strings, % has no special meaning and needs no escaping; instead, escape braces by doubling them ({{ and }}).
  • string.Template uses $ as its marker, so % and {} are always literal; escape a dollar sign with $$.
  • Raw strings (r"...") do not affect percent or brace interpretation; they only suppress backslash escapes.
  • When maintaining mixed codebases, identify which formatting method each string uses before choosing your escape strategy.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.