[Python-Dev] transitioning from % to {} formatting

James Y Knight foom at fuhm.net
Wed Sep 30 18:19:31 CEST 2009

On Sep 30, 2009, at 10:34 AM, Steven D'Aprano wrote:
>> E.g.
>> x = newstyle_formatstr("{} {} {}")
>> x % (1,2,3) == x.format(1,2,3) == "1 2 3"
> Moving along, let's suppose the newstyle_formatstr is introduced.  
> What's
> the intention then? Do we go through the std lib and replace every  
> call
> to (say)
>    somestring % args
> with
>    newstyle_formatstr(somestring) % args
> instead? That seems terribly pointless to me

Indeed, that *would* be terribly pointless! Actually, more than  
pointless, it would be broken, as you've changed the API from taking  
oldstyle format strings to newstyle format strings.

That is not the suggestion. The intention is to change /nearly  
nothing/ in the std lib, and yet allow users to use newstyle string  
substitution with every API.

Many Python APIs (e.g. logging) currently take a %-type formatting  
string. It cannot simply be changed to take a {}-type format string,  
because of backwards compatibility concerns. Either a new API can be  
added to every one of those functions/classes, or, a single API can be  
added to inform those places to use newstyle format strings.

>> This could allow for a controlled switch towards the new format
>> string format, with a long deprecation period for users to migrate:
>> 1) introduce the above feature, and recommend in docs that people
>> only ever use new-style format strings, wrapping the string in
>> newstyle_formatstr() when necessary for passing to an API which uses
>> % internally.
> And how are people supposed to know what the API uses internally?

It's documented, (as it already must be, today!).

> Personally, I think your chances of getting people to write:
> logging.Formatter(newstyle_formatstr("%(asctime)s - %(name)s - % 
> (level)s - %(msg)s"))
> instead of
> logging.Formatter("%(asctime)s - %(name)s - %(level)s - %(msg)s")

That's not my proposal.

The user could write either:
logging.Formatter("%(asctime)s - %(name)s - %(level)s - %(msg)s")
(as always -- that can't be changed without a long deprecation  
period), or:
logging.Formatter(newstyle_formatstr("{asctime} - {name} - {level} -  

This despite the fact that logging has not been changed to use {}- 
style formatting internally. It should continue to call "self._fmt %  
record.__dict__" for backward compatibility.

That's not to say that this proposal would allow no work to be done to  
check the stdlib for issues. The Logging module presents one: it  
checks if the format string contains "%{asctime}" to see if it should  
bother to calculate the time. That of course would need to be changed.  
Best would be to stick an instance which lazily generates its string  
representation into the dict. The other APIs mentioned on this thread  
(BaseHTTPServer, email.generator) will work immediately without  
changes, however.


More information about the Python-Dev mailing list