38

How do I transform a classic string to an f-string?

variable = 42
user_input = "The answer is {variable}"
print(user_input)

Output: The answer is {variable}

f_user_input = # Here the operation to go from a string to an f-string
print(f_user_input)

Desired output: The answer is 42

wjandrea
  • 28,235
  • 9
  • 60
  • 81
François M.
  • 4,027
  • 11
  • 30
  • 81

5 Answers5

66

An f-string is syntax, not an object type. You can't convert an arbitrary string to that syntax, the syntax creates a string object, not the other way around.

I'm assuming you want to use user_input as a template, so just use the str.format() method on the user_input object:

variable = 42
user_input = "The answer is {variable}"
formatted = user_input.format(variable=variable)

If you wanted to provide a configurable templating service, create a namespace dictionary with all fields that can be interpolated, and use str.format() with the **kwargs call syntax to apply the namespace:

namespace = {'foo': 42, 'bar': 'spam, spam, spam, ham and eggs'}
formatted = user_input.format(**namespace)

The user can then use any of the keys in the namespace in {...} fields (or none, unused fields are ignored).

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Ok, I get it. But it means I have to know all values that the user can enter, which is not the case : the input will be an SQL query, and I can't really know what the user will enter : `select * from {table} where day = {day} and client = {client}`. Any idea on how I can do it in this case ? – François M. Jun 26 '17 at 10:27
  • 1
    @fmalaussena: so what values would arbitrary entries give you? You can parse the format upfront and see what fiednames are used, see [Dynamic fields in a Python string](//stackoverflow.com/q/36193379) and [How to get the variable names from the string for the format() method](//stackoverflow.com/q/22830226) – Martijn Pieters Jun 26 '17 at 10:32
  • locals() function can help here to pass all local variable as arguments. `formatted = user_input.format(**locals())` – Arjun Ariyil Feb 28 '23 at 10:11
  • @ArjunAriyil from a security standpoint that’s not a good idea, do you want to give an end-user access to **all** local variables? – Martijn Pieters Feb 28 '23 at 10:55
  • @MartijnPieters, Yes Agreed. It is not a secure way. But the first commend sounds like this is what he is trying to achieve. This can be used only when we can completely trust the source of user_input. But I guess using `locals()` is better than the other answers that suggest to use `eval`. – Arjun Ariyil Feb 28 '23 at 12:05
15

The real answer is probably: don't do this. By treating user input as an f-string, you are treating it like code which creates a security risk. You have to be really certain you can trust the source of the input.

If you are in situation where you know the user input can be trusted, you can do this with eval():

variable = 42
user_input="The answer is {variable}"
eval("f'{}'".format(user_input))
'The answer is 42'

Edited to add: @wjandrea pointed out another answer which expands on this.

Von
  • 4,365
  • 2
  • 29
  • 29
  • 2
    Here's [an answer](https://stackoverflow.com/a/47599254/4518341) that expands on the safety aspect – wjandrea Jul 18 '20 at 19:12
  • 1
    @Von +1 for the answer because it allows also to handle inner expression e.g. `"The answer is {variable+1}"`, which raises `KeyError` with the `format` method invoked on normal strings (non f-strings). However, this solution is not 100% reliable because it assumes that the string does not contain simple quotes, e.g. `user_input="The 'answer' is {variable}"` raises a `SyntaxError`. Here is a way to fix such issue: `eval(f"f{repr(user_input)}")` – Pierre Denis Apr 13 '22 at 12:30
6
variable = 42
user_input = "The answer is {variable}"
# in order to get The answer is 42, we can follow this method
print (user_input.format(variable=variable))

(or)

user_input_formatted = user_input.format(variable=variable)
print (user_input_formatted)

Good link https://cito.github.io/blog/f-strings/

priya raj
  • 362
  • 2
  • 8
4

Just to add one more similar way how to do the same. But str.format() option is much preferable to use.

variable = 42
user_input = "The answer is {variable}"
print(eval(f"f'{user_input}'"))

A safer way to achieve the same as Martijn Pieters mentioned above:

def dynamic_string(my_str, **kwargs):
    return my_str.format(**kwargs)

variable = 42
user_input = "The answer is {variable}"
print('1: ', dynamic_string(my_str=user_input, variable=variable))
print('2: ', dynamic_string(user_input, variable=42))
1:  The answer is 42
2:  The answer is 42
Kostia Medvid
  • 1,211
  • 13
  • 13
-7

You can use f-string instead of normal string.

variable = 42
user_input = f"The answer is {variable}"
print(user_input)