views:

103

answers:

2

Hi,

Is there a way to use python string.format such that no exception is thrown when an index is missing, instead an empty string is inserted.

result = "i am an {error} example string {error2}".format(hello=2,error2="success")

here,result should be :

"i am an   example string success"

Right now, python throws a keyerror and stops formatting. Is it possible to change this behavior ?

Thanks

Edit:

There exists Template.safe_substitute (even that leaves the pattern intact instead of inserting an empty string) , but couldn't something similar for string.format

The desired behavior would be similar to string substitution in php.

class Formatter(string.Formatter):
  def get_value(self,key,args,kwargs):
    try:
        if hasattr(key,"__mod__"):
            return args[key]
        else:
            return kwargs[key]
    except:
        return ""

This seems to provide the desired behavior.

+5  A: 

Unfortunately, no, there is no such way to do by default. However you can provide it defaultdict or object with overridden __getattr__, and use like this:

class SafeFormat(object):
    def __init__(self, **kw):
        self.__dict = kw

    def __getattr__(self, name):
        if not name.startswith('__'):
            return self.__dict.get(name, '')

print "i am an {0.error} example string {0.error2}".format(SafeFormat(hello=2,error2="success"))
i am an  example string success
Daniel Kluev
Thanks. Its userful, but as Fabian mentioned, doesn't handle mapping objects other than dict
Code freak
+2  A: 

str.format() doesn't expect a mapping object. Try this:

from collections import defaultdict

d = defaultdict(str)
d['error2'] = "success"
s = "i am an {0[error]} example string {0[error2]}"
print s.format(d)

You make a defaultdict with a str() factory that returns "". Then you make one key for the defaultdict. In the format string, you access keys of the first object passed. This has the advantage of allowing you to pass other keys and values, as long as your defaultdict is the first argument to format().

Also, see http://bugs.python.org/issue6081

Fabian Fagerholm
Could this be improved by using a formatter object (idea frm the bug report link) instead of a defaultdict ? that way, no change wud be reqd to the format variable.Thanks
Code freak
class Formatter(string.Formatter): def get_value(self,key,args,kwargs): try: if hasattr(key,"__mod__"): return args[key] else: return kwargs[key] except: return ""This works for me. The advantage is that there's no need to create an extra defaultdict.
Code freak
Yeah, that works well. I'm not sure how to compare the penalty of an extra defaultdict against the penalty of an extra Formatter class+object, but in some situations it might be better, especially if it makes the code clearer.
Fabian Fagerholm