'Automatically convert old string formatting style into f-strings

How could I convert Python's old-style formatting strings, like this:

print("You: %s points. Me: %s points." % (score, total - score))

into the following?

print(f"You: {score} points. Me: {total - score} points.")

In fact, for the case of two %s, I have written this regular expression:

  • search: "(.*)%s(.*)%s(.*)" % \(([^,\)]+), ([^,\)]+)\)
  • replace: f"$1{$4}$2{$5}$3"

One could easily write several other regexes for handling the 1, 3, 4, ... %s's cases, but I am looking for a more general and error-prone approach.

Note: AFAIK, a similar question was asked here in 2013 (Automatic conversion of the advanced string formatter from the old style), when the f-strings were not a thing (they were introduced in Python 3.6).



Solution 1:[1]

Use flynt. You call it with the name of a directory and it recursively searches for all .py files and converts % formatting to f-strings.

flynt <directory_to_process>

It will convert .format() calls as well as % formatting.

You can install it with

pip install flynt

Be warned that converting % to f-strings is not perfect and will produce a different result if you were passing a single element tuple into them (which is why Python moved away from % formatting).

Solution 2:[2]

Use pyupgrade. Specifically, to enable converting to f-strings, use

pyupgrade --py36-plus <filename>

You can install it with

pip install pyupgrade

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Boris Verkhovskiy