2

How can I retrieve the expected format key name from a string?

Lets say I have:

"This string expects {expected}"

If I input the wrong key name python throws a KeyError showing the expected name.

"This string expects {expected}".format(whoops="wrong key")
KeyError: 'expected'

Is there a way to test for this without regex or (ugh) purposely throwing the KeyError? I've looked over the string documentation but nothing jumped out at me.

Edit 1:

I do not want to suppress the error, nor do I want to silently fill it with None/empty string. I want to use the expected keyname to properly format the string.

I could rework it upstream by mapping the strings to the keyname in a dict, but was hoping to avoid that if there is a way to find this after the fact.

Regex would be a good solution, but at this point I am just curious more than anything.

Verbal_Kint
  • 1,366
  • 3
  • 19
  • 35

3 Answers3

5

You can use Formatter.parse like that:

>>> s="{a} {b} {c}"
>>> list(string.Formatter.parse("",s))
[('', 'a', '', None), (' ', 'b', '', None), (' ', 'c', '', None)]
>>> [t[1] for t in string.Formatter.parse("",s)]
['a', 'b', 'c']
Ohad Eytan
  • 8,114
  • 1
  • 22
  • 31
2

Listen, this is a very nice question,
and it made me busy for the last 5 minutes or so

Here is a function I wrote to do the job.
No regex, but yes exceptions. Here it goes:

def findKeys(s):
    keys = {}
    while True:
        try:
            s.format(**keys)
            return [*keys.keys()]
        except KeyError as e:
            k, = e.args
            keys[k] = ''

It returns a list of all the keys inside the string.

Israel Unterman
  • 13,158
  • 4
  • 28
  • 35
  • Good thinking! I did something similar, but without try/except: http://stackoverflow.com/a/39153155/2044940 – CodeManX Aug 25 '16 at 19:21
0

To find the keyname you would need to wrap it in a try/except clause.

try:
    my_string = "This string expects {expected}".format(whoops="wrong key")
except KeyError as e:
    print(e)  # the variable e is your keyname

Edit: Another method could be to find the curly brackets within the string and use a slice to locate your keyname. The example below only finds the first instance of a keyname but could easily be modified to find additional keys.

s = "This string expects {expected}"
key_name = s[s.find('{') + 1: s.find('}')]
A Magoon
  • 1,180
  • 2
  • 13
  • 21