0% found this document useful (0 votes)
29 views8 pages

Python String Formatting Best Practices

Uploaded by

dhanunjayav2007
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
29 views8 pages

Python String Formatting Best Practices

Uploaded by

dhanunjayav2007
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 8

Python >>>

>>> errno = 50159747054


>>> name = 'Bob'

— FREE Email Series —


Based on these variables, you’d like to generate an output string containing a simple
🐍 Python Tricks 💌 error message:

Python >>>

'Hey Bob, there is a 0xbadc0ffee error!'

That error could really spoil a dev’s Monday morning… But we’re here to discuss
string formatting. So let’s get to work.

Email…
#1 “Old Style” String Formatting (%
Get Python Tricks » Operator)
Python String Formatting Best 🔒 No spam. Unsubscribe any
Strings in Python have a unique built-in operation that can be accessed with the %
operator. This lets you do simple positional formatting very easily. If you’ve ever
Practices time.
worked with a printf-style function in C, you’ll recognize how this works instantly.
Here’s a simple example:
by Dan Bader  Jul 04, 2018  26 Comments
 basics best-practices python  Browse Topics Python >>>

 Guided Learning Paths >>> 'Hello, %s' % name


Mark as Completed   Tweet  Share  Email
 Basics  Intermediate "Hello, Bob"
 Advanced

I’m using the %s format specifier here to tell Python where to substitute the value of
Table of Contents api best-practices career
name, represented as a string.
community databases data-science
#1 “Old Style” String Formatting (% Operator)
data-structures data-viz devops There are other format specifiers available that let you control the output format.
#2 “New Style” String Formatting (str.format)
django docker editors flask For example, it’s possible to convert numbers to hexadecimal notation or add
#3 String Interpolation / f-Strings (Python 3.6+)
front-end gamedev gui whitespace padding to generate nicely formatted tables and reports. (See Python
#4 Template Strings (Standard Library)
machine-learning numpy projects Docs: “printf-style String Formatting”.)
Which String Formatting Method Should You Use?
python testing tools web-dev
Key Takeaways
web-scraping Here, you can use the %x format specifier to convert an int value to a string and to
represent it as a hexadecimal number:

Python >>>

>>> '%x' % errno


 Remove ads 'badc0ffee'

 Watch Now This tutorial has a related video course created by the Real The “old style” string formatting syntax changes slightly if you want to make
Python team. Watch it together with the written tutorial to deepen your multiple substitutions in a single string. Because the % operator takes only one
understanding: Python String Formatting Tips & Best Practices argument, you need to wrap the right-hand side in a tuple, like so:

Python >>>
Remember the Zen of Python and how there should be “one obvious way to do
something in Python”? You might scratch your head when you find out that there are >>> 'Hey %s, there is a 0x%x error!' % (name, errno)
'Hey Bob, there is a 0xbadc0ffee error!'
four major ways to do string formatting in Python.

In this tutorial, you’ll learn the four main approaches to string formatting in Python, It’s also possible to refer to variable substitutions by name in your format string, if
as well as their strengths and weaknesses. You’ll also get a simple rule of thumb for you pass a mapping to the % operator:
how to pick the best general purpose string formatting approach in your own
programs. Python >>>

>>> 'Hey %(name)s, there is a 0x%(errno)x error!' % {


Let’s jump right in, as we’ve got a lot to cover. In order to have a simple toy example
... "name": name, "errno": errno }
for experimentation, let’s assume you’ve got the following variables (or constants, 'Hey Bob, there is a 0xbadc0ffee error!'
Help
really) to work with:
This makes your format strings easier to maintain and easier to modify in the future.
“The formatting operations described here exhibit a variety of quirks that lead
You don’t have to worry about making sure the order you’re passing in the values
to a number of common errors (such as failing to display tuples and
matches up with the order in which the values are referenced in the format string. Of
dictionaries correctly). Using the newer formatted string literals or the
course, the downside is that this technique requires a little more typing.
str.format() interface helps avoid these errors. These alternatives also provide
I’m sure you’ve been wondering why this printf-style formatting is called “old style” more powerful, flexible and extensible approaches to formatting text.”
string formatting. It was technically superseded by “new style” formatting in Python (Source)
3, which we’re going to talk about next.
This is why I’d personally try to stick with str.format for new code moving forward.
Starting with Python 3.6, there’s yet another way to format your strings. I’ll tell you
all about it in the next section.

 Remove ads
#3 String Interpolation / f-Strings (Python
#2 “New Style” String Formatting 3.6+)
(str.format) Python 3.6 added a new string formatting approach called formatted string literals
or “f-strings”. This new way of formatting strings lets you use embedded Python
Python 3 introduced a new way to do string formatting that was also later back- expressions inside string constants. Here’s a simple example to give you a feel for the
ported to Python 2.7. This “new style” string formatting gets rid of the %-operator feature:
special syntax and makes the syntax for string formatting more regular. Formatting
is now handled by calling .format() on a string object. Python >>>

>>> f'Hello, {name}!'


You can use format() to do simple positional formatting, just like you could with “old 'Hello, Bob!'
style” formatting:

Python >>> As you can see, this prefixes the string constant with the letter “f“—hence the name
“f-strings.” This new formatting syntax is powerful. Because you can embed arbitrary
>>> 'Hello, {}'.format(name)
'Hello, Bob' Python expressions, you can even do inline arithmetic with it. Check out this
example:

Or, you can refer to your variable substitutions by name and use them in any order Python >>>
you want. This is quite a powerful feature as it allows for re-arranging the order of
>>> a = 5
display without changing the arguments passed to format(): >>> b = 10
>>> f'Five plus ten is {a + b} and not {2 * (a + b)}.'
Python >>>
'Five plus ten is 15 and not 30.'

>>> 'Hey {name}, there is a 0x{errno:x} error!'.format(


... name=name, errno=errno)
Formatted string literals are a Python parser feature that converts f-strings into a
'Hey Bob, there is a 0xbadc0ffee error!'
series of string constants and expressions. They then get joined up to build the final
string.
This also shows that the syntax to format an int variable as a hexadecimal string has
changed. Now you need to pass a format spec by adding a :x suffix. The format Imagine you had the following greet() function that contains an f-string:
string syntax has become more powerful without complicating the simpler use
Python >>>
cases. It pays off to read up on this string formatting mini-language in the Python
documentation. >>> def greet(name, question):
... return f"Hello, {name}! How's it {question}?"
In Python 3, this “new style” string formatting is to be preferred over %-style ...
>>> greet('Bob', 'going')
formatting. While “old style” formatting has been de-emphasized, it has not been
"Hello, Bob! How's it going?"
deprecated. It is still supported in the latest versions of Python. According to this
discussion on the Python dev email list and this issue on the Python dev bug tracker,
%-formatting is going to stick around for a long time to come.
When you disassemble the function and inspect what’s going on behind the scenes,
you’ll see that the f-string in the function gets transformed into something similar to
Still, the official Python 3 documentation doesn’t exactly recommend “old style” the following:
formatting or speak too fondly of it:
Python >>>

>>> def greet(name, question):


... return "Hello, " + name + "! How's it " + question + "?"

The real implementation is slightly faster than that because it uses the BUILD_STRING
opcode as an optimization. But functionally they’re the same:
Python >>> So when should you use template strings in your Python programs? In my opinion,
>>> import dis the best time to use template strings is when you’re handling formatted strings
>>> dis.dis(greet) generated by users of your program. Due to their reduced complexity, template
2 0 LOAD_CONST 1 ('Hello, ') strings are a safer choice.
2 LOAD_FAST 0 (name)
4 FORMAT_VALUE 0 The more complex formatting mini-languages of the other string formatting
6 LOAD_CONST 2 ("! How's it ")
techniques might introduce security vulnerabilities to your programs. For example,
8 LOAD_FAST 1 (question)
10 FORMAT_VALUE 0 it’s possible for format strings to access arbitrary variables in your program.
12 LOAD_CONST 3 ('?')
14 BUILD_STRING 5 That means, if a malicious user can supply a format string, they can potentially leak
16 RETURN_VALUE secret keys and other sensitive information! Here’s a simple proof of concept of how
this attack might be used against your code:
String literals also support the existing format string syntax of the str.format()
Python >>>
method. That allows you to solve the same formatting problems we’ve discussed in
the previous two sections: >>> # This is our super secret key:
>>> SECRET = 'this-is-a-secret'
Python >>>
>>> class Error:
>>> f"Hey {name}, there's a {errno:#x} error!" ... def __init__(self):
"Hey Bob, there's a 0xbadc0ffee error!" ... pass

>>> # A malicious user can craft a format string that


Python’s new formatted string literals are similar to JavaScript’s Template Literals >>> # can read data from the global namespace:
added in ES2015. I think they’re quite a nice addition to Python, and I’ve already >>> user_input = '{error.__init__.__globals__[SECRET]}'
started using them in my day to day (Python 3) work. You can learn more about
>>> # This allows them to exfiltrate sensitive information,
formatted string literals in our in-depth Python f-strings tutorial.
>>> # like the secret key:
>>> err = Error()
>>> user_input.format(error=err)
'this-is-a-secret'

 Remove ads
See how a hypothetical attacker was able to extract our secret string by accessing
the __globals__ dictionary from a malicious format string? Scary, huh? Template
#4 Template Strings (Standard Library) strings close this attack vector. This makes them a safer choice if you’re handling
format strings generated from user input:
Here’s one more tool for string formatting in Python: template strings. It’s a simpler
and less powerful mechanism, but in some cases this might be exactly what you’re Python >>>

looking for. >>> user_input = '${error.__init__.__globals__[SECRET]}'


>>> Template(user_input).substitute(error=err)
Let’s take a look at a simple greeting example: ValueError:
"Invalid placeholder in string: line 1, col 1"
Python >>>

>>> from string import Template


>>> t = Template('Hey, $name!')
>>> t.substitute(name=name)
'Hey, Bob!'
Which String Formatting Method Should You
Use?
You see here that we need to import the Template class from Python’s built-in string I totally get that having so much choice for how to format your strings in Python can
module. Template strings are not a core language feature but they’re supplied by the feel very confusing. This is an excellent cue to bust out this handy flowchart
string module in the standard library. infographic I’ve put together for you:

Another difference is that template strings don’t allow format specifiers. So in order
to get the previous error string example to work, you’ll need to manually transform
the int error number into a hex-string:

Python >>>

>>> templ_string = 'Hey $name, there is a $error error!'


>>> Template(templ_string).substitute(
... name=name, error=hex(errno))
'Hey Bob, there is a 0xbadc0ffee error!'

That worked great.


Get a short & sweet Python Trick delivered to your inbox every couple of
days. No spam ever. Unsubscribe any time. Curated by the Real Python
team.

Table of Contents Email Address


#1 “Old Style” String Formatting
(% Operator) Send Me Python Tricks »
#2 “New Style” String Formatting
(str.format)
#3 String Interpolation / f-Strings
(Python 3.6+)
#4 Template Strings (Standard About Dan Bader
Library)

Which String Formatting Method


Should You Use? Dan Bader is the owner and editor in chief of Real Python and the main developer of the
Python String Formatting Rule of Thumb (Image: Click to Tweet) → Key Takeaways realpython.com learning platform. Dan has been writing code for more than 20 years and holds a
master's degree in computer science.
This flowchart is based on the rule of thumb that I apply when I’m writing Python:
Mark as Completed  » More about Dan
Python String Formatting Rule of Thumb: If your format strings are user-
supplied, use Template Strings (#4) to avoid security issues. Otherwise, use
Literal String Interpolation/f-Strings (#3) if you’re on Python 3.6+, and “New
 Tweet  Share  Email
Style” str.format (#2) if you’re not.

Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who
 Recommended Video Course
worked on this tutorial are:
Key Takeaways Python String Formatting Tips &
Best Practices
Perhaps surprisingly, there’s more than one way to handle string formatting in
Python. Aldren Joanna
Each method has its individual pros and cons. Your use case will influence
which method you should use.
If you’re having trouble deciding which string formatting method to use, try
our Python String Formatting Rule of Thumb.

Mark as Completed  Master Real-World Python Skills


With Unlimited Access to Real Python
 Watch Now This tutorial has a related video course created by the Real
Python team. Watch it together with the written tutorial to deepen your
understanding: Python String Formatting Tips & Best Practices

🐍 Python Tricks 💌

Join us and get access to thousands of


tutorials, hands-on video courses, and
a community of expert Pythonistas:
Level Up Your Python Skills » 27 Comments 
1

G Join the discussion…


What Do You Think?
LOG IN WITH OR SIGN UP WITH DISQUS ?

Rate this article: Name

 Tweet  Share  Share  Email

 21 Share Best Newest Oldest


What’s your #1 takeaway or favorite thing you learned? How are you going to
put your newfound skills to use? Leave a comment below and let us know. CHUKWUKADIBIA − ⚑
5 years ago

There should be a button to clap for articles on here because this was just amazing.
Commenting Tips: The most useful comments are those written with the
goal of learning from or helping out other students. Get tips for asking 11 Reply • Share ›

good questions and get answers to common questions in our support


portal.
Dan Bader RP Team > CHUKWUKADIBIA
− ⚑
5 years ago

Haha thanks, great to hear you liked the article :-)

Looking for a real-time conversation? Visit the Real Python Community 0 Reply • Share ›

Chat or join the next “Office Hours” Live Q&A Session. Happy Pythoning!
RandyP − ⚑
5 years ago

You might want to include something here on writing log messages from `logging`, which I believe provides for printf-style
ALSO ON REAL PYTHON
formatting. E.g.
`logging.info("%d is a number, OK %s?", 5, 'Fred')`
I think I read somewhere that there's a good performance reason to use that instead of f-strings.

Python Modules and Python Classes: The What Can I Do With 2 Reply • Share ›
Packages – An … Power of … Python? – Real Python
Maciej Urbański > RandyP
− ⚑
This article explores Python In this tutorial, you'll learn In this tutorial, you'll find a 5 years ago
modules and Python how to create and use full- set of guidelines that will It's not only about performance - the lazily evaluating string formatting so it doesn't get called when specified log
packages, two … featured classes in your … help you start applying …
message level is not even enabled.
What may prove to be even more important, for log aggregators, like http://sentry.io/, to work correctly you need to
supply %-formatting and its arguments to logging call.

If you go with any of


logging.warning('foo bar %s' % err)
logging.warning('foo bar {}'.format(err))
logging.warning(f'foo bar {err}')

instead of
logging.warning('foo bar %s', 'baz')

„foo bar baz” and „foo bar qux” will be treated as entirely different class of warnings.

Every time I introduced Sentry into a project I was quickly overwhelmed by issue notifications (which should have been
deduplicated), just because of this and had to quickly fixup logging in the whole code base just to make the sentry
usable. I'm talking couple of orders of magnitude difference here in amount of "different" issues reported.

It very common mistake, I'm guessing in part because, like you can see here, most of the time when discussing string
formatting logging module is not even mentioned.

4 Reply • Share ›

Bearcat Şándor − ⚑
4 years ago

In my python class the first print method we were taught was like so
print("My name is", user_name)
Why was this not listed in the methods? Is it obsolete or of any use?
I tend to avoid it anyway, as i have a C background, but i'm curious.

3 Reply • Share ›

C
CH > Bearcat Şándor
− ⚑
4 years ago

Because that's not string formatting, it's just printing two strings.

1 Reply • Share ›
Gustavo Chaves − ⚑
2 years ago Casey Morrison − ⚑
2 years ago
TIMTOWTDI! :-)
Thank you!!! This is short and sweet; and it rocks!
1 Reply • Share ›
0 Reply • Share ›
Chanchana Sornsoontorn − ⚑
5 years ago edited
J
Jesus Espinoza − ⚑
2 years ago
That "badc0ffee" error made me confused for a minute. I thought it was "bad coffee" string.
I was wondering why '%x' format is outputting a string instead of a hexadecimal number. And I saw that it's all made of Great Tutorial + Video Tutorial!!! Easy to understand!!! Thank you!!!
hexadecimal digits.
Sometimes, joke makes you get stuff harder.
0 Reply • Share ›

1 Reply • Share ›
J
Jurandy Soares − ⚑
3 years ago

Pekka Klärck − ⚑ Which program did you use to draw the flowchart?
5 years ago edited

I mostly agree with your flowchart, but due to `str.format` not handling non-ASCII values nicely in Python 2 I'm still using the old
0 Reply • Share ›

style in my Python 2/3 code. The problem I referred to is this:


C
Carlos García Montoro − ⚑
3 years ago
```
>>> print '%s esimerkki' % u'Hyvä' Really nice article. I have learnt some new techniques/styles that I was not aware of.
Hyvä esimerkki
I only miss one thing: I'd love to read about how to format strings for the logger in modern Python. I've always read that one
>>> print '{} esimerkki'.format(u'Hyvä')
should use the old style because the string is not formatted/constructed until it has to be logged, and therefore, if a message is
Traceback (most recent call last):
not going to be logged due to the logger level, it is not formatted when using the old style, whereas using the new style it is
File "<stdin>", line 1, in <module>
formatted and fully created.
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 3: ordinal not in range(128)
``` Can you add a section in the article on how to format strings for logger in modern python, or at least, can you provide a link where
this is handled?
The problem can be avoided by using `unicode.format` (e.g. `u'{} esimerkki'.format(u'Hyvä')`) but forgetting that `u` is *very* easy
and will bite you only if the supplied argument happens to contain non-ASCII chars. Thanks!
1 Reply • Share › 0 Reply • Share ›

Maciej Urbański > Pekka Klärck


− ⚑ Dan Bader RP Team > Carlos García Montoro 3 years ago
− ⚑
5 years ago
Thanks Carlos! We've got a couple of tutorials & resources on logging in Python, you can find them here: Python logging
from __future__ import unicode_literals resources on Real Python

and you don't have to remember to include u ever again. Although you will see a need to use b from time to time. Still, it 0 Reply • Share ›
is better to use from __future__ imports heavily, as it one of the ways of making your codes Python 3 ready.

0 Reply • Share ›
C
Carlos García Montoro > Dan Bader 3 years ago
− ⚑
Thanks!
Sapna Sainee > Pekka Klärck
− ⚑ 0 Reply • Share ›
5 years ago

nice ex Guy Arad − ⚑


4 years ago
0 Reply • Share ›
Good and clear article!
gamesbook > Sapna Sainee − ⚑ However, you should include mention of performance. The `%` is more efficient than `.format` but string-interpolation is the most
efficient (from my benchmarks)
5 years ago

Does this same problem arise using the {var} syntax from Python 3.6? 0 Reply • Share ›

@Dan - maybe you can update this article to reflect this issue - which is a key one for European programmers (I
get that US programmers mostly only care about English).
John Salerno − ⚑
4 years ago

0 Reply • Share › Wow, I found this article because I was searching for a refresher on how to use the %s method. I had no idea Python had
introduced these other methods into the language! Thanks!

R
Roger Larsson > gamesbook 3 years ago
− ⚑
0 Reply • Share ›
Internationalization... are kind of user supplied strings.

Seeing that the new improved f-strings do not handle that at all is kind of sad...
brookm291 − ⚑
4 years ago

The best looking alternative Thank you


f(_('Hey, {username}')))
0 Reply • Share ›
How to use gettext with python 3.6 f-strings

Can after translation execute any code supplied by translator, and I wonder if not all of the f-strings F
Firigion Puff − ⚑
4 years ago
speed advantage is lost too...
Just one added note: maybe it's just that I don't know ho to do it, but a reason to use New style strings over literal string
0 Reply • Share › interpolation is that with theformer, you can unpack lists and dictionaries into the formatting arguments.

S
shannon carey − ⚑ stuff_to_do = 1, 2, 3
print('First I'm gonna do {}, then {} and last {}.'.format(*stuff_to_do)
a year ago

f-strings are not lazy though, right? 0 Reply • Share ›

0 Reply • Share ›
− ⚑
J
john brown
J
john brown
4 years ago

Never got past the so-called coffee 'joke'...

0 Reply • Share ›

derekgreer − ⚑
5 years ago

love the flow chart

0 Reply • Share ›

André Silvestre − ⚑
5 years ago

Very good. Thanks!

0 Reply • Share ›

Subscribe Privacy Do Not Sell My Data

Keep Learning

Related Tutorial Categories: basics best-practices python

Recommended Video Course: Python String Formatting Tips & Best Practices
 Remove ads

© 2012–2023 Real Python ⋅ Newsletter ⋅ Podcast ⋅ YouTube ⋅ Twitter ⋅ Facebook ⋅ Instagram ⋅


Python Tutorials ⋅ Search ⋅ Privacy Policy ⋅ Energy Policy ⋅ Advertise ⋅ Contact
❤️ Happy Pythoning!

You might also like