-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
Is your feature request related to a problem? Please describe
In my experiments W1202 is misleading as f-strings performance is virtually equivalent to %-operator formatting in practice.
Describe the solution you'd like
W1202 be deprecated, as it can lead people to not use f-strings, which (if available) are the preferred mechanism for string interpolation.
Additional context
This is related to my inquiry around this warning: #2354
To verify my hypothesis that f-strings are virtually as performant as %-operator formatting I wrote the following snippet to explore timing related to log statements with the 3 approaches (f-strings, .format(), and %-operator). This was on a Django app I'm working on.
import timeit
def timeitex1(num_times):
fstring = timeit.timeit(
'logging.info(f"""this is a {thing}, and thing: {thing + "blah"}""")',
setup="import logging ; thing='1234'",
number=num_times,
)
formattim = timeit.timeit(
'logging.info("this is a {}, and thing: {}".format(thing, thing + "blah"))',
setup="import logging ; thing='1234'",
number=num_times,
)
percentop = timeit.timeit(
'logging.info("this is a %s, and thing: %s", thing, thing + "blah")',
setup="import logging ; thing='1234'",
number=num_times,
)
return (fstring, formattim, percentop)
With logging output disabled (ie in my Django settings I had: LOGGING["loggers"] = {}), %-formatting and f-strings are virtually identical.
num_times = 10,000:
(0.016536445124074817, 0.02152163698337972, 0.018616185057908297)
num_times = 100,000:
(0.16004435811191797, 0.20005284599028528, 0.1561291899997741)
num_times = 1,000,000:
(1.641325417906046, 2.0023047979921103, 1.6249939629342407)
Returned times are tuples of "time for f-strings", "time for the format() call", and "time for %-formatting".
That's a difference of ~1% (1.641325417906046 vs 1.6249939629342407 seconds) between f-strings & the %-operator on the largest run (.format calls being clearly slower).
With logging enabled, it's a total wash (technically f-strings was the winner in the larger runs but by such a small margin it's inconsequential). This is with log output going to standard out (so I only went up to 100,000 entries as I didn't want to dump 3 million log statements to my console):
num_times = 10,000:
(1.6245153648778796, 2.0137458329554647, 1.6029843359719962)
num_times = 100,000:
(4.39409149507992, 4.51585376705043, 4.532764581032097)
So basically unless you are emitting a ton of logging statements for a level that are never actually logged (say because the LOG_LEVEL is set high), then it doesn't matter. And if you're in that scenario, then really there's no noticeable difference between %-operator formatting or f-strings (just don't do .format() calls).
OTOH, if you are emitting the logging message, then it's likely that the f-string approach will be faster, so following W1202 will actually make your code (extremely slightly) slower.