str.format() raises KeyError
Asked Answered
S

2

97

The following code raises a KeyError exception:

addr_list_formatted = []
addr_list_idx = 0

for addr in addr_list: # addr_list is a list
    addr_list_idx = addr_list_idx + 1
    addr_list_formatted.append("""
        "{0}"
        {
        "gamedir"  "str"
        "address"  "{1}"
        }
    """.format(addr_list_idx, addr))

Why?

I am using Python 3.1.

Sleepyhead answered 2/5, 2010 at 22:6 Comment(2)
You could probably accomplish the same task with a list comprehension (use enumerate to get the indeces).Roee
See also (duplicate) #35574849Carnap
F
172

The problem is that those { and } characters you have there don't specify a key for formatting. You need to double them up, so change your code to:

addr_list_formatted.append("""
    "{0}"
    {{
    "gamedir"  "str"
    "address"  "{1}"
    }}
""".format(addr_list_idx, addr))
Fruity answered 2/5, 2010 at 22:30 Comment(4)
What if someone wanted to use JSON in Python?Crummy
@Crummy the double { in the answer is just to tell the format method that there is no key to format here (so they are escaped in the formated string and it shouldn't be a problem for build a JSON that way). Alternatively there is other efficient ways to manipulate strings, like the join method : "".join(['{"', var_name, '":', value, '}'])Palla
I almost lost my mind until figured whats the problemDiskson
@DmitryKankalovich You have lost your mind, Stack Overflow, and everybody here, is just a figment of your imagination. (that's what I keep telling myself at least) :)Fruity
T
5

Using str.format() to format JSON strings is not ideal because you would have to escape the curly braces, as the accepted answer notes.

While this method may be suitable for small JSON templates, it could make the template difficult to read if there are many curly braces that require escaping.

A better alternative could be string.Template:

from string import Template

addr_list = ["address 1, country 1", "address 2, country 2"]

addr_list_formatted = []
addr_list_idx = 0

template = Template("""
"${index}"
{
"gamedir"  "str"
"address"  "${address}"
}
""")

for addr in addr_list:
    addr_list_idx = addr_list_idx + 1
    formatted = template.substitute(index=addr_list_idx, address=addr)
    addr_list_formatted.append(formatted)
Trocar answered 26/2, 2023 at 22:33 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.