How can I find the keyword argument passed to a c-style python string
Given:
bill eats apple
'%(name)s eats %(fruit)s'
Should get
{ 'name': 'bill', 'fruit' : 'apple'}
If you do not want to use parse, you can convert your pattern string to a regular expression using named groups and then use re.match and match.groupdict to get the mapping.
>>> text = "bill eats apple"
>>> a = "%(name)s eats %(fruit)s"
>>> p = re.sub(r"%\((\w+)\)s", r"(?P<\1>\w+)", a)
>>> p
'(?P<name>\\w+) eats (?P<fruit>\\w+)'
>>> re.match(p, text).groupdict()
{'fruit': 'apple', 'name': 'bill'}
Note that \w+ will only match a single word. To allow for more complex names, you might instead use e.g. [^(]+ to match anything up to the closing )
>>> text = "billy bob bobbins eats a juicy apple"
>>> p = re.sub(r"%\((\w+)\)s", r"(?P<\1>[^)]+)", a)
>>> re.match(p, text).groupdict()
{'fruit': 'a juicy apple', 'name': 'billy bob bobbins'}
name has a space in between.\w+ with something more complex, maybe [^)]+ or similar.sre_constants.error: unbalanced parenthesisre works magic. Using parse would have required changing everything given I was using django translations it would be more cubersome. And replacing `%' prior to using parse would also not be possible since now the translations won't work.First, there is no function or package in Python that allow you to do that with old style (aka C style) string formatting. A good reference about reversing c-style string format.
The best you can have is a giant regex pattern and as you know it's really not a perfect solution.
That said,
As @smarx said in comments, you can use parse which is well fitted for that, but, from the given doc's link:
parse() is the opposite of format()
That mean you needs to use format() instead of %, which is a good thing because % is Python's string formatting old style where format() is the new style and the best to use since Python3 (it's python 2.7 / 3 compliant, but not %).
Here is an example with format():
print(parse.parse('{name} eats {fruit}', 'bill eats apple'))
<Result () {'fruit': 'apple', 'name': 'bill'}>
If you are not confortable with format() I advise you to give a look at pyformat.org, a really good guide.
format() or use homemade regex pattern and hope it will works in most of case. Again, even if that needs to change texts I advise you to use format()replace %( with { and )s with } prior to using parse?
parsemodule a try.reand stuff only.parsemodule? (If not, why not? If so, why wouldn't you just use the module?){}type parameters.