Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Python string.format KeyError with variable key

I’m pulling in text strings with placeholders for instance attributes. I’m trying to write something that will get the place holder text, find the attribute with that name, and swap it in. I’m able to get the attribute, but to swap it in I’m having to hard code the placeholder.

The "new_text_string = …" line gives me "KeyError: ‘dntier’"
The commented line below it works, but I don’t want to have to hard code every possible attribute.

import re

class Test:
    def __init__(self,mdtier,rxtier,dntier,vstier):
        self.mdtier = mdtier,
        self.rxtier = rxtier,
        self.dntier = dntier,
        self.vstier = vstier,


rec = Test('You Only','You Only','You + Family','You + Spouse')
text_string = 'Dental coverage for {dntier}.'

try:
    text_variable = re.search('\{(.+?)\}', text_string).group(1)
except AttributeError:
    text_variable = '' 
if text_variable:
    replacement = getattr(rec, text_variable)[0]
    new_text_string = text_string.format(text_variable=replacement)
    #new_text_string = text_string.format(dntier=replacement)
else:
    new_text_string = text_string

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

The error you see is because this line

text_string.format(text_variable=replacement)

will replace a variable named text_variable, but the string template is looking for a variable named dntier. That is, the variable name is not evaluated, but passed literally.

Since you’re trying to pass a keyword argument with a dynamic name, I suggest creating a dict and using **:

new_text_string = text_string.format(**{text_variable: replacement})

Or, to simplify the code even further, you can use rec.__dict__:

import re

class Test:
    def __init__(self,mdtier,rxtier,dntier,vstier):
        self.mdtier = mdtier,
        self.rxtier = rxtier,
        self.dntier = dntier,
        self.vstier = vstier,

rec = Test('You Only','You Only','You + Family','You + Spouse')
text_string = 'Dental coverage for {dntier}.'
print(text_string.format(**rec.__dict__))
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading