The official solution (Python 3 Docs) for strings in format mappings is to subclass the dict class and to define the magic-method __missing__(). This method is called whenever a key is missing, and what it returns is used for the string formatting instead:

class format_dict(dict):
    def __missing__(self, key):
        return "..."

d = format_dict({"foo": "name"})

print("My %(foo)s is %(bar)s" % d) # "My name is ..."

print("My {foo} is {bar}".format(**d)) # "My name is ..."

Edit: the second print() works in Python 3.5.3, but it does not in e.g. 3.7.2: KeyError: 'bar' is raised and I couldn't find a way to catch it.

After some experiments, I found a difference in Python's behavior. In v3.5.3, the calls are __getitem__(self, "foo") which succeeds and __getitem__(self, "bar") which can not find the key "bar", therefore it calls __missing__(self, "bar") to handle the missing key without throwing a KeyError. In v3.7.2, __getattribute__(self, "keys") is called internally. The built-in keys() method is used to return an iterator over the keys, which yields "foo", __getitem__("foo") succeeds, then the iterator is exhausted. For {bar} from the format string there is no key "bar". __getitem__() and hence __missing_() are not called to handle the situation. Instead, the KeyError is thrown. I don't know how one could catch it, if at all.

In Python 3.2+ you should use format_map() instead (also see Python Bug Tracker - Issue 6081):

from collections import defaultdict
    
d = defaultdict(lambda: "...")
d.update({"foo": "name"})

print("My {foo} is {bar}".format_map(d)) # "My name is ..."

If you want to keep the placeholders, you can do:

class Default(dict):
    def __missing__(self, key): 
        return key.join("{}")
    
d = Default({"foo": "name"})

print("My {foo} is {bar}".format_map(d)) # "My name is {bar}"

As you can see, format_map() does call __missing__().

The following appears to be the most compatible solution as it also works in older Python versions including 2.x (I tested v2.7.15):

class Default(dict):
    def __missing__(self, key):
        return key.join("{}")

d = Default({"foo": "name"})

import string
print(string.Formatter().vformat("My {foo} is {bar}", (), d)) # "My name is {bar}"

To keep placeholders as-is including the format spec (e.g. {bar:<15}) the Formatter needs to be subclassed:

import string

class Unformatted:
    def __init__(self, key):
        self.key = key
    def __format__(self, format_spec):
        return "{{{}{}}}".format(self.key, ":" + format_spec if format_spec else "")

class Formatter(string.Formatter):
    def get_value(self, key, args, kwargs):
        if isinstance(key, int):
            try:
                return args[key]
            except IndexError:
                return Unformatted(key)
        else:
            try:
                return kwargs[key]
            except KeyError:
                return Unformatted(key)


f = Formatter()
s1 = f.vformat("My {0} {1} {foo:<10} is {bar:<15}!", ["real"], {"foo": "name"})
s2 = f.vformat(s1, [None, "actual"], {"bar":"Geraldine"})
print(s1) # "My real {1} name       is {bar:<15}!"
print(s2) # "My real actual name       is Geraldine      !"

Note that the placeholder indices are not changed ({1} remains in the string without a {0}), and in order to substitute {1} you need to pass an array with any odd first element and what you want to substitute the remaining placeholder with as second element (e.g. [None, "actual"]).

You can also call the format() method with positional and named arguments:

s1 = f.format("My {0} {1} {foo:<10} is {bar:<15}!", "real", foo="name")
s2 = f.format(s1, None, "actual", bar="Geraldine")
Answer from CodeManX on Stack Overflow
Top answer
1 of 4
24

The official solution (Python 3 Docs) for strings in format mappings is to subclass the dict class and to define the magic-method __missing__(). This method is called whenever a key is missing, and what it returns is used for the string formatting instead:

class format_dict(dict):
    def __missing__(self, key):
        return "..."

d = format_dict({"foo": "name"})

print("My %(foo)s is %(bar)s" % d) # "My name is ..."

print("My {foo} is {bar}".format(**d)) # "My name is ..."

Edit: the second print() works in Python 3.5.3, but it does not in e.g. 3.7.2: KeyError: 'bar' is raised and I couldn't find a way to catch it.

After some experiments, I found a difference in Python's behavior. In v3.5.3, the calls are __getitem__(self, "foo") which succeeds and __getitem__(self, "bar") which can not find the key "bar", therefore it calls __missing__(self, "bar") to handle the missing key without throwing a KeyError. In v3.7.2, __getattribute__(self, "keys") is called internally. The built-in keys() method is used to return an iterator over the keys, which yields "foo", __getitem__("foo") succeeds, then the iterator is exhausted. For {bar} from the format string there is no key "bar". __getitem__() and hence __missing_() are not called to handle the situation. Instead, the KeyError is thrown. I don't know how one could catch it, if at all.

In Python 3.2+ you should use format_map() instead (also see Python Bug Tracker - Issue 6081):

from collections import defaultdict
    
d = defaultdict(lambda: "...")
d.update({"foo": "name"})

print("My {foo} is {bar}".format_map(d)) # "My name is ..."

If you want to keep the placeholders, you can do:

class Default(dict):
    def __missing__(self, key): 
        return key.join("{}")
    
d = Default({"foo": "name"})

print("My {foo} is {bar}".format_map(d)) # "My name is {bar}"

As you can see, format_map() does call __missing__().

The following appears to be the most compatible solution as it also works in older Python versions including 2.x (I tested v2.7.15):

class Default(dict):
    def __missing__(self, key):
        return key.join("{}")

d = Default({"foo": "name"})

import string
print(string.Formatter().vformat("My {foo} is {bar}", (), d)) # "My name is {bar}"

To keep placeholders as-is including the format spec (e.g. {bar:<15}) the Formatter needs to be subclassed:

import string

class Unformatted:
    def __init__(self, key):
        self.key = key
    def __format__(self, format_spec):
        return "{{{}{}}}".format(self.key, ":" + format_spec if format_spec else "")

class Formatter(string.Formatter):
    def get_value(self, key, args, kwargs):
        if isinstance(key, int):
            try:
                return args[key]
            except IndexError:
                return Unformatted(key)
        else:
            try:
                return kwargs[key]
            except KeyError:
                return Unformatted(key)


f = Formatter()
s1 = f.vformat("My {0} {1} {foo:<10} is {bar:<15}!", ["real"], {"foo": "name"})
s2 = f.vformat(s1, [None, "actual"], {"bar":"Geraldine"})
print(s1) # "My real {1} name       is {bar:<15}!"
print(s2) # "My real actual name       is Geraldine      !"

Note that the placeholder indices are not changed ({1} remains in the string without a {0}), and in order to substitute {1} you need to pass an array with any odd first element and what you want to substitute the remaining placeholder with as second element (e.g. [None, "actual"]).

You can also call the format() method with positional and named arguments:

s1 = f.format("My {0} {1} {foo:<10} is {bar:<15}!", "real", foo="name")
s2 = f.format(s1, None, "actual", bar="Geraldine")
2 of 4
20

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

Discussions

Python format throws KeyError - Stack Overflow
The following code snippet: template = "\ function routes(app, model){\ ... More on stackoverflow.com
🌐 stackoverflow.com
KeyError in string format when curlies { } present
I'm running into the same problem as #767 and used a similar fix, but one that still tries to do the formatting. So my message is Retrying timed. .wrapped_fn in 0.9077886023569136 ... More on github.com
🌐 github.com
14
October 18, 2023
Do not use Python's str.format() for expanding placeholders in commands
Placeholders in command environment ... using Python's str.format(): https://github.com/pypa/cibuildwheel/blob/main/cibuildwheel/util.py#L41 · This makes it (nearly) impossible to use curly braces in a command, because a pair of single braces will throw a KeyError exception ... More on github.com
🌐 github.com
46
September 22, 2021
Format function: Fill missing keys with empty string
Python has default dict, where it returns a default value on non-existing keys: >>> from collections import defaultdict >>> dd = defaultdict(list) >>> dd["nosuchkey"] [] More on reddit.com
🌐 r/learnpython
4
2
February 5, 2020
🌐
Awscd
awscd.com › ErrorMessage › Python › format-ignore-missing-keys.html
Python format ignore missing keys
python string format suppress/silent keyerror/indexerror - Stack Overflow https://stackoverflow.com/questions/3536303/python-string-format-suppress-silent-keyerror-indexerror・・・
🌐
AskPython
askpython.com › home › using python string format_map()
Using Python String format_map() - AskPython
August 6, 2022 - Well, format() does not handle this for us, and it simply raises a KeyError exception. This is because it copies the mapping to a new dictionary object. Because the mapping is on a new dictionary object (not using our subclass), it does not ...
🌐
Python
docs.python.org › 3.0 › library › string.html
string — Common string operations — Python v3.0.1 documentation
December 18, 2020 - Like substitute(), except that if placeholders are missing from mapping and kws, instead of raising a KeyError exception, the original placeholder will appear in the resulting string intact.
🌐
GitHub
github.com › Delgan › loguru › issues › 1008
KeyError in string format when curlies { } present · Issue #1008 · Delgan/loguru
October 18, 2023 - class SafeDict(dict): def __missing__(self, key): return '{' + key + '}' ... try: log_record["message"] = message.format(*args, **kwargs) except (KeyError, IndexError): # KeyError from { missing_key } in message, IndexError from missing positional ...
Author   Delgan
Find elsewhere
🌐
GitHub
github.com › pypa › cibuildwheel › issues › 840
Do not use Python's str.format() for expanding placeholders in commands · Issue #840 · pypa/cibuildwheel
September 22, 2021 - Placeholders in command environment ... using Python's str.format(): https://github.com/pypa/cibuildwheel/blob/main/cibuildwheel/util.py#L41 · This makes it (nearly) impossible to use curly braces in a command, because a pair of single braces will throw a KeyError exception ...
Author   pypa
🌐
Reddit
reddit.com › r/learnpython › format function: fill missing keys with empty string
r/learnpython on Reddit: Format function: Fill missing keys with empty string
February 5, 2020 -

Hey guys,

I'm working in a very specific enviroment and I have a scheme file where I replace keys with the format function. The file might look like this:

1: {code1}
2: {code2}
3: {code3}

I want that other persons can change the format file and add {code} tags. My program uses this file and replaces the values, but the amount of {code} blocks varies.

So at the moment I generate a dict with the code tags, and replace them in that string (which got loaded from the file)

code_tags = {"code1": "ABC", "code2": "DEF"}
file_content.format(**code_tags)

A problem occurs when there are more keys in the scheme file than keys generated from my program (KeyError). How can I put in an empty string for tags which got not specified in code_tags?

I thought about crawling the file and find every tag, compare, and add missing to the dict with and emptry string. But that's kinda hask-ish and maybe not the cleanest style.

How would you solve the problem?

🌐
Aquiles
notes.aquiles.me › tech_notes › python_partial_string_formatting
Formatting strings in two steps with Python | Aquiles Carattino
July 8, 2020 - The thing is that I want to format the string using only val1 and leaving the part concerning val2 intact, because that will be passed down to some other code. Basically, I want this: ... But if we try, we get a KeyError because val2 is missing. This means that Python is using a dictionary to handle the formatting, and if we could somehow get in between, we can actually skip the error and return the unformatted part of the string.
🌐
Python.org
discuss.python.org › python help
Please help: Key Error: ' ' - Python Help - Discussions on Python.org
June 8, 2021 - Hello I am new to learning the Python language and I am currently teaching myself by going through a ten-week bootcamp book for beginners. I have encounter this error: Key Error: ’ ’ The book utilises Python 3.7 and…
🌐
Reddit
reddit.com › r/learnpython › keyerror: '\n type'
r/learnpython on Reddit: KeyError: '\n type'
November 10, 2022 -

Hey I've been working on a project and I came across a error of: KeyError: '\n type'

I've been looking online for solutions but I've only found KeyError: '\n' (without the 'type' and none of the solutions work). What I'm trying to do is take a list and get a chart back from quickchart.io. Its worked fine without using variable data, but now that im trying to it isn't working.

My code:

import quickchart from QuickChart
coins = ['1','2','3','4','5']
bags = ['1','2','3','4','5']
cash = ['1','2','3','4','5']
qc = QuickChart()
qc.width = 1000
qc.height = 600
qc.version = "2"
qc.config = '''{
        type: 'line',
        data: {
          labels: ['24hrs', '18hrs', '12hrs', '6hrs', 'now'],
          datasets: [
            {
              label: 'coins',
              borderColor: 'rgb(255, 99, 132)',
              backgroundColor: 'rgba(255, 99, 132, .5)',
              data: {},
            },
            {
              label: 'bags',
              borderColor: 'rgb(54, 162, 235)',
              backgroundColor: 'rgba(54, 162, 235, .5)',
              data: {},
            },
            {
              label: 'cash',
              borderColor: 'rgb(75, 192, 192)',
              backgroundColor: 'rgba(75, 192, 192, .5)',
              data: {},
            },
          ],
        },
        options: {
          responsive: true,
          title: {
            display: true,
            text: 'Stock Market',
          },
          tooltips: {
            mode: 'index',
          },
          hover: {
            mode: 'index',
          },
          scales: {
            xAxes: [
              {
                scaleLabel: {
                  display: true,
                  labelString: 'Time Since',
                },
              },
            ],
            yAxes: [
              {
                stacked: true,
                scaleLabel: {
                  display: true,
                  labelString: 'Value',
                },
              },
            ],
          },
        },
      }'''.format(coins, bags, cash) #This is the line causing the error according to my console

the indents in the stringed-dict may be stuffed up from copy and paste, but hopefully that doesn't cause an issue for you.

I've also tried doing :

...
data: ['{}','{}','{}','{}','{}']
...
}'''.format(coins[0], coins[1]) #and so on

which has the same error

In case you need it, is the documentation for quickchart (https://quickchart.io/documentation/)

let me know if you need other information, I'd be happy to give it to you.

🌐
GitHub
github.com › hwchase17 › langchain › issues › 7079
KeyError when formatting FewShotPromptTemplate · Issue #7079 · langchain-ai/langchain
July 3, 2023 - KeyError Traceback (most recent call last) Cell In[1], line 56 53 new_doc = "Kate McConnell is 56 and is soon retired according to the current laws of the state of Alaska in which she resides." 54 new_entities_to_extract = ['name', 'organization'] ---> 56 prompt = few_shot_prompt_template.format( 57 input_doc=new_doc, 58 entities_to_extract=new_entities_to_extract, 59 answer={} 60 ) File [~/Desktop/automarkup/.venv/lib/python3.9/site-packages/langchain/prompts/few_shot.py:123](https://file+.vscode-resource.vscode-cdn.net/Users/username/Desktop/automarkup/src/~/Desktop/automarkup/.venv/lib/python3.9/site-packages/langchain/prompts/few_shot.py:123), in FewShotPromptTemplate.format(self, **kwargs) 120 template = self.example_separator.join([piece for piece in pieces if piece]) 122 # Format the template with the input variables.
Author   langchain-ai
🌐
Reddit
reddit.com › r/learnpython › how to get .format() to ignore a specific {} that is in a string?
r/learnpython on Reddit: How to get .format() to ignore a specific {} that is in a string?
July 14, 2018 -

I have a text file that gets read in to the program, and it also contains a JSON file.

An example of what I'm talking about is this:

Hello, {}. Welcome to /r/{}. This is a JSON file.

---

{ 
    "key": "value"
}

That is stored in a text file that we will call example.txt. I read the file in as such:

def read_text_file(file_name):
    with open(file_name, "r") as file:
        return file.read()

my_string = read_text_file("example.txt")
formatted_string = my_string.format(username, subreddit)

However, because the dictionary also has a {} in it, .format() seems to expect a third argument with .format(). Is there a way to make it ignore the third one so that I don't get a KeyError exception?

🌐
STechies
stechies.com › python-keyerror
Python KeyError Exceptions - How to Resolve it with Example
Try and except block will help you to avoid the keyError. The try and except is the keyword. Try block statements will execute first then except. Everything executed well then except block will ignore.