2

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!

2
  • Can you add what do you what for output for this example? Is it '25-08-2017 10:26:11 host type'? Commented Aug 25, 2017 at 15:46
  • 1
    Here's how you would do it using format: print("{0} {1[host]} {1[type]}".format(datetime,dictionary["_source"])) Read more about format here Commented Aug 25, 2017 at 15:48

5 Answers 5

6

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

Sign up to request clarification or add additional context in comments.

Comments

3

You're better off using the format method:

>>> "{} {d[host]} {d[type]}".format(datetime, d=dictionary["_source"])
'25-08-2017 10:26:11 host type'

Comments

2

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'
    

Comments

2

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.

Comments

1

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))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.