I have been using this function for some time now, which casts the Dict of inputted keyword arguments as a SafeDict object that subclasses Dict.
def safeformat(str, **kwargs):
class SafeDict(dict):
def __missing__(self, key):
return '{' + key + '}'
replacements = SafeDict(**kwargs)
return str.format_map(replacements)
I didn't make this up, but I think it's a good solution. The one downside is that you can't call mystring.safeformat(**kwargs) - of course, you have to call safeformat(mystring,**kwargs).
If you're really interested in being able to call mystr.safeformat(**kwargs) (which I am interested in doing!), consider using this:
class safestr(str):
def safeformat(self, **kwargs):
class SafeDict(dict):
def __missing__(self, key):
return '{' + key + '}'
replacements = SafeDict(**kwargs)
return safestr(self.format_map(replacements))
You can then create a safestr object as a = safestr(mystr) (for some str called mystr), and you can in fact call
mystr.safeformat(**kwargs).
e.g.
mysafestr = safestr('Hey, {friendname}. I am {myname}.')
print(mysafestr.safeformat(friendname='Bill'))
prints
Hey, Bill. I am {myname}.
This is cool in some ways - you can pass around a partially-formatted safestr, and could call safeformat in different contexts. I especially like to call mystr.format(**locals()) to format with the appropriate namespace variables; the safeformat method is especially useful in this case, because I don't always carefully looks through my namespace.
The main issue with this is that inherited methods from str return a str object, not a safestr. So mysafestr.lower().safeformat(**kwargs) fails. Of course you could cast as a safestr when using safeformat:
safestr(mysafestr.lower()).safeformat(**kwargs),
but that's less than ideal looking. I wish Python just gave the str class a safeformat method of some kind.