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