Evaluation of variable as f-string
Johannes Bauer
dfnsonfsduifb at gmx.de
Mon Jan 23 11:24:15 EST 2023
Hi there,
is there an easy way to evaluate a string stored in a variable as if it
were an f-string at runtime?
I.e., what I want is to be able to do this:
x = { "y": "z" }
print(f"-> {x['y']}")
This prints "-> z", as expected. But consider:
x = { "y": "z" }
s = "-> {x['y']}"
print(s.format(x = x))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: "'y'"
Even though
s = "-> {x}"
print(s.format(x = x))
Prints the expected "-> {'y': 'z'}".
This is supposedly for security reasons. However, when trying to emulate
this behavior that I wanted (and know the security implications of), my
solutions will tend to be less secure. Here is what I have been thinking
about:
1. Somehow wrap "s" into an f-string, then eval. E.g.:
eval("f'" + s + "'")
This is a pain in the ass because you have to know what kind of
quotation signs are used inside the expression. In the given case, this
wouldn't work (but 'f"' prefix and '"' suffix would).
2. Parse the expression (regex?), then eval() the individual arguments,
then run through format(). Pain in the ass to get the exact same
behavior as f-strings. Probably by regex alone not even guaranteed to be
parsable (especially corner cases with escaped '{' signs or ':' or '{'
included inside the expression as a literal).
3. Somehow compile the bytecode representing an actual f-string
expression, then execute it. Sounds like a royal pain in the butt, have
not tried it.
All solutions are extremely undesirable and come with heavy drawbacks.
Is there any standard solution (Py3.10+) that does what I would?
Anything I'm missing?
Thanks,
Johannes
More information about the Python-list
mailing list