Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Python interpreting this string as a dictionary when formatting? [duplicate]

I am having problems using format with a string which looks like a Python dictionary.

I want to generate the following string: {"one":1} If I try to do it as:

'{"one":{}}'.format(1)

the interpreter throws a KeyError:

>>> a = '{"one":{}}'.format(1)
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
KeyError: '"one"'

I understand that the issue probably revolves around the fact that the string contains {, which can be confused with format's {}. Why is this happening exactly and how can it be solved?

I know of percentage formatting, but I'd like to find a solution that doesn't involve ditching format().

like image 286
user2891462 Avatar asked Sep 11 '17 14:09

user2891462


3 Answers

Braces can be escaped by using double braces, use:

'{{"one":{}}}'.format(1)
like image 197
v.coder Avatar answered Oct 18 '22 04:10

v.coder


You need doubled curly braces {{ }} to escape curly braces in string formatting.

a= '{{"one":{}}}'.format(1)

from doc:

Format strings contain “replacement fields” surrounded by curly braces {}. Anything that is not contained in braces is considered literal text, which is copied unchanged to the output. If you need to include a brace character in the literal text, it can be escaped by doubling: {{ and }}.

If you do not escape braces, str.format() will look for the value of key '"one"' to format the string. For example:

b = '{"one"} foo'.format(**{'"one"':1})
print(b) # 1 foo
like image 26
floatingpurr Avatar answered Oct 18 '22 04:10

floatingpurr


The formatting of '{"one": {}}' is using an identifier as the field_name and will essentially try to look for a keyword argument that's been supplied to .format and has the name '"one"'.

As the docs state:

The field_name itself begins with an arg_name that is either a number or a keyword. If it’s a number, it refers to a positional argument, and if it’s a keyword, it refers to a named keyword argument.

(emphasis mine)

That's why you get the KeyError exception; it tries to look for a key in the mapping of keyword arguments provided to format. (which, in this case, is empty, hence the error).

As a solution, just escape the outer curly braces:

>>> '{{"one":{}}}'.format(1)
'{"one":1}'

The same remedy applies if you decide on using f-strings in the future:

>>> f'{{"one": {1}}}'
'{"one": 1}'
like image 17
Dimitris Fasarakis Hilliard Avatar answered Oct 18 '22 04:10

Dimitris Fasarakis Hilliard