Python'S Many Ways of String Formatting - Are the Older Ones (Going to Be) Deprecated

Python's many ways of string formatting — are the older ones (going to be) deprecated?

While there are various indications in the docs that .format and f-strings are superior to % strings, there's no surviving plan to ever deprecate the latter.

In commit Issue #14123: Explicitly mention that old style % string formatting has caveats but is not going away any time soon., inspired by issue Indicate that there are no current plans to deprecate printf-style formatting, the docs on %-formatting were edited to contain this phrase:

As the new string-formatting syntax is more flexible and handles tuples and dictionaries naturally, it is recommended for new code. However, there are no current plans to deprecate printf-style formatting.

(Emphasis mine.)

This phrase was removed later, in commit Close #4966: revamp the sequence docs in order to better explain the state of modern Python. This might seem like a sign that a plan to deprecate % formatting was back on the cards... but diving into the bug tracker reveals that the intent was the opposite. On the bug tracker, the author of the commit characterises the change like this:

  • changed the prose that describes the relationship between printf-style formatting and the str.format method (deliberately removing the implication that the former is any real danger of disappearing - it's simply not practical for us to seriously contemplate killing it off)

In other words, we've had two consecutive changes to the %-formatting docs intended to explicitly emphasise that it will not be deprecated, let alone removed. The docs remain opinionated on the relative merits of different kinds of string formatting, but they're also clear the %-formatting isn't going to get deprecated or removed.

What's more, the most recent change to that paragraph, in March 2017, changed it from this...

The formatting operations described here exhibit a variety of quirks that lead to a number of common errors (such as failing to display tuples and dictionaries correctly). Using the newer formatted string literals or the str.format interface helps avoid these errors. These alternatives also provide more powerful, flexible and extensible approaches to formatting text.

... to this:

The formatting operations described here exhibit a variety of quirks that lead to a number of common errors (such as failing to display tuples and dictionaries correctly). Using the newer formatted string literals, the str.format interface, or template strings may help avoid these errors. Each of these alternatives provides their own trade-offs and benefits of simplicity, flexibility, and/or extensibility.

Notice the change from "helps avoid" to "may help avoid", and how the clear recommendation of .format and f-strings has been replaced by fluffy, equivocal prose about how each style "provides their own trade-offs and benefits". That is, not only is a formal deprecation no longer on the cards, but the current docs are openly acknowledging that % formatting at least has some "benefits" over the other approaches.

I'd infer from all this that the movement to deprecate or remove % formatting has not only faltered, but been defeated thoroughly and permanently.

Is string formatting with % still allowed in Python 3.x?

This is not a definitive answer, but it is too large to make the point in a comment. The change in documentation wording in subsequent versions definitely moves away from stating the % syntax is deprecated.

From Old String Formatting Operations in v3.0 and Old String Formatting Operations in v3.1:

The formatting operations described here are obsolete and may go away in future versions of Python.

From Old String Formatting Operations in v3.2:

However, there are no current plans to deprecate printf-style formatting.

Old String Formatting Operations in v3.3 makes no mention of deprecation plans.

This is not quite certain enough for me to consider it actionable, however, and it would be nice to find a source with a clear statement.

is string formatter `% + tuple` deprecated?

Even without speaking about performance, because in python 3 % could be deleted, format is preferred.

Old string formatting:

Since str.format() is quite new, a lot of Python code still uses the %
operator. However, because this old style of formatting will
eventually be removed from the language, str.format() should generally
be used.

f-strings vs str.format()

I'm afraid that it will be deprecated during the next Python versions

Don't be, str.format does not appear (nor has a reason) to be leaving any time soon, the PEP that introduced fprefixed-strings even states in its Abstract:

This PEP does not propose to remove or deprecate any of the existing string formatting mechanisms.

Formatted strings were introduced to address some of the shortcomings other methods for formatting strings had; not to throw the old methods away and force god-knows how many projects to use f-string's if they want their code to work for Python 3.6+.


As for the performance of these, it seems my initial suspicion that they might be slower is wrong, f-strings seem to easily outperform their .format counterparts:

➜ cpython git:(master) ./python -m timeit -s "a = 'test'" "f'formatting a string {a}'"
500000 loops, best of 5: 628 nsec per loop
➜ cpython git:(master) ./python -m timeit "'formatting a string {a}'.format(a='test')"
100000 loops, best of 5: 2.03 usec per loop

These were done against the master branch of the CPython repository as of this writing; they are definitely subject to change:

  • f-strings, as a new feature, might have possible optimizations
  • Optimizations to CPython might make .format faster (e.g Speedup method calls 1.2x)

But really, don't worry about speed so much, worry about what is more readable to you and to others.

In many cases, that's going to be f-strings, but there's some cases where format is better.

Which are safe methods and practices for string formatting with user input in Python 3?

It doesn't matter which format you choose, any format and library can have its own downsides and vulnerabilities. The bigger questions you need to ask yourself is what is the risk factor and the scenario you are facing with, and what are you going to do about it.
First ask yourself: will there be a scenario where a user or an external entity of some kind (for example - an external system) sends you a format string? If the answer is no, there is no risk. If the answer is yes, you need to see whether this is needed or not. If not - remove it to eliminate the risk.
If you need it - you can perform whitelist-based input validation and exclude all format-specific special characters from the list of permitted characters, in order to eliminate the risk. For example, no format string can pass the ^[a-zA-Z0-9\s]*$ generic regular expression.

So the bottom line is: it doesn't matter which format string type you use, what's really important is what do you do with it and how can you reduce and eliminate the risk of it being tampered.

String formatting expressions (Python)

The original idea was to gradually switch to str.format() approach while allowing both ways:

PEP 3101:

The new system does not collide with any of the method names of the existing string formatting techniques, so both systems can co-exist until it comes time to deprecate the older system.

The idea is still being pursued:

We are still encouraging people to use the new str.format().
Python Issue 7343

Since the original '%' approach is planned to be deprecated and removed at some point in the future, I would suggest writing new code with str.format(). Though at the moment, it is just a matter of personal preference. I personally prefer using dictionary-based formatting, which is supported by both '%' operator and str.format() method.

Right speech mark placement for Python code

Try this:

print(f'You will need,{fivekgs} 5kg blocks and, {onekgs} 1kg blocks!')

Formatting text. (Python)

txt.format(txt(price)) attempts to call txt as if it were a function, when it is in fact a string, hence the error.

You probably want to be calling:

print(txt.format(price))

instead.



Related Topics



Leave a reply



Submit