[Python-ideas] String Format Callable Flag (Was: Efficient Debug Logging)
Steven D'Aprano
steve at pearwood.info
Sat Feb 18 02:25:43 EST 2017
On Fri, Feb 17, 2017 at 11:37:04AM -0500, Mark E. Haase wrote:
> Python has two string formatting mini-languages.
Four. % string formatting, .format method, f-strings, string.Template
strings.
But who's counting? :-)
> Both allow formatting
> flags, for example in "%03d", the "0" (zero) is a flag that means to pad
> with leading zeroes. I propose to add a string format flag to both
> mini-languages that explicitly says, "this argument is callable, and its
> *return value* should be formatted."
The % string format codes are intentionally limited to more-or-less the
similar codes available in C, and won't be given any newer functionality.
It's really only f-strings and .format method that this change could be
applied to.
[...]
> The suggested change is to add a "C" flag to the formatting language that
> indicates an argument is callable. When formatting the string, the argument
> will be called and its result will be used for the formatting operation.
> The C flag must be handled before any other flags, regardless of the order
> in which they are specified. The callable's return value is then formatted
> according to the rest of the specifier.
>
> With this change, the above example can now be written as:
>
> >>> expensive = lambda: 2
> >>> logging.debug('%03d %C03d', 1, expensive)
>
> The "expensive" code is not executed at this log level.
I see three problems:
(1) It will be a bug magnet. People will accidently write
logging.debug('%03d %C03d', 1, expensive())
and then not only will their code still be slow, but they'll have to
debug mysterious
TypeError: 'int' object is not callable
exceptions, but only *sometimes*. Most insideously, these Heisenbugs
will only occur when they turn the log level all the way up to
debugging, which will crash their program *before* logging the error!
(2) It requires the expensive calculation to be wrapped in a lambda:
logging.debug('%03d %C03d', 1, lambda: nth_prime(10**8) + 1)
which I guess is kind of Python's way of spelling a thunk, but people
don't like using lambda for that.
(3) It is useless for delaying evaluation of something that isn't going
to be converted into a string.
--
Steven
More information about the Python-ideas
mailing list