Reputation: 1704
I have a dictionary and a datetime object I converted to string. How do I print the datetime string and several items from the dictionary in the same line?
For example:
dictionary = {"_source": {"host": "host", "type": "type"}}
datetime = '25-08-2017 10:26:11'
This is what I'm trying to print:
print("%s %(host)s %(type)s" % (datetime,dictionary["_source"]))
Getting an error on the datetime string:
TypeError: format requires a mapping
Thanks!
Upvotes: 2
Views: 3304
Reputation: 2046
Like others have said it is probably the best to use str.format(). The closest option with method str.format() to your question is code which Violet Red suggested in his answer:
"{} {host} {type}".format(datetime,**dictionary["_source"])
But if you really want or need to use the old way of formatting (using %
) then you can try some of these options:
Separating string into two or more strings
Like Eugene Yarmash explained in his answer you can't mix ordinary and mapping format specifiers in same string, but you could separate it to two (or more) strings like this:
'%s' % datetime + ' %(type)s %(host)s' % dictionary["_source"]
This will work but if you wanted to print datetime
in the middle (something like this '%(type)s %s %(host)s'
) or if you have more ordinary and mapping format specifiers which are intertwined (something like this '%s '%(type)s %s %(host)s' %s
). You could separate '%(type)s %s %(host)s'
into multiple strings like this:
'%(type)s' % dictionary["_source"] + ' %s ' % datetime + '%(host)s' % dictionary["_source"]
But then there is no point in string format in first place.
First applying mapping than ordinary format specifiers
This method solves our problem of formatting string with ordinary and mapping format specifiers which are intertwined. I will explain this method on the example from OP. We have string '%s %(type)s %(host)s'
which we want to format. Like I said in first we apply mapping format specifiers:
print('%s %(type)s %(host)s' % dictionary["_source"])
If we do this it will print out:
'{'type': 'type', 'host': 'host'} type host'
This does not work, but what we can do is add parentheses ()
in every ordinary format specifier and update our dictionary with {'': '%s'}
:
print('%()s %(type)s %(host)s' % {'type': 'type', 'host': 'host', '': '%s'})
This will print out:
'%s type host'
which we can easily format with % (datetime)
.
The question is how to {'': '%s'}
to your dictionary. You have two options, to use a function or to define your class for the dictionary object.
1. Using function
def ForFormat(x):
d = x.copy()
d.update({'': '%s'})
return d
And you use it like this:
print('%()s %(type)s %(host)s' % ForFormat(dictionary["_source"]) % (datetime))
The result is exactly what we want:
'25-08-2017 10:26:11 type 45 host'
2. Creating class
class FormatDict(dict):
def __missing__(self, key):
return '%s'
Here we don't actually add {'': '%s'}
to dictionary, but rather change its method __missing__()
which is called when key can not be found in dictionary so it will retrun '%s'
for each mapping format specifier that is not in dictionary. It is used like this:
print('%()s %(type)s %(host)s' % FormatDict(dictionary["_source"]) % (datetime))
It also prints out the desired result:
'25-08-2017 10:26:11 type 45 host'
Upvotes: 2
Reputation: 150031
You can't mix ordinary and mapping format specifiers in a single format string. You should use either
"%s %s %s" % (param1, param2, param3)
or
"%(key1)s %(key2)s %(key3)s" % {"key1": val1, "key2": val2, "key3": val3}
In Python 3.6+ you can use much more convenient and efficient f-strings for interpolation, e.g:
f'{val1} {val2} {val3}'
where replacement fields are expressions evaluated at run time.
Upvotes: 2
Reputation: 71471
You can try this:
dictionary = {"_source": {"host": "host", "type": "type"}}
datetime = '25-08-2017 10:26:11'
print("host {} type {} datetime {}".format(dictionary["_source"]["host"], dictionary["_source"]["type"], datetime))
Upvotes: 1
Reputation: 221
One way is to assign a name to your datetime arg:
"{t} {host} {type}".format(t=datetime,**dictionary["_source"])
But actually it will work even without it
"{} {host} {type}".format(datetime,**dictionary["_source"])
though it's better to use named values in formatted strings imo
Upvotes: 6