Je lisais ce blog sur les nouvelles chaînes f de python et elles semblent vraiment bien. Cependant, je veux pouvoir charger une chaîne f à partir d'une chaîne ou d'un fichier.
Je n'arrive pas à trouver une méthode de chaîne ou une autre fonction qui fait cela.
De l'exemple dans mon lien ci-dessus:
name = 'Fred'
age = 42
f"My name is {name} and I am {age} years old"
'My name is Fred and I am 42 years old'
Mais que faire si j'avais une chaîne s
? Je veux pouvoir eff-ify s
, quelque chose comme ceci:
name = 'Fred'
age = 42
s = "My name is {name} and I am {age} years old"
effify(s)
Il s'avère que je peux déjà effectuer quelque chose de similaire à str.format
et obtenir la reprise de performance. À savoir:
format = lambda name, age: f"My name is {name} and I am {age} years old"
format('Ted', 12)
'My name is Ted and I am 12 years old'
les chaînes f sont du code. Pas seulement dans le coffre-fort, "bien sûr, un littéral de chaîne est du code", mais dans la manière dangereuse d'exécuter du code arbitraire. Ceci est une chaîne f valide:
f"{__import__('os').system('install ransomware or something')}"
et il exécutera des commandes Shell arbitraires lorsqu'il sera évalué.
Vous demandez comment prendre une chaîne chargée à partir d'un fichier texte et l'évaluer en tant que code, et la réponse se résume à eval
. Il s'agit bien sûr d'un risque de sécurité et probablement une mauvaise idée, donc je recommande de ne pas essayer de charger des chaînes f à partir de fichiers.
Si vous souhaitez charger la chaîne f f"My name is {name} and I am {age} years old"
à partir d'un fichier, puis mettre
f"My name is {name} and I am {age} years old"
dans le fichier, f
et les guillemets et tout.
Lisez-le à partir du fichier, compilez-le et enregistrez-le (donc eval
n'a pas à le recompiler à chaque fois):
compiled_fstring = compile(fstring_from_file, '<fstring_from_file>', 'eval')
et l'évaluer avec eval
:
formatted_output = eval(compiled_fstring)
Si vous faites cela, faites très attention aux sources à partir desquelles vous chargez vos f-strings.
Mais si j'avais une chaîne s? Je veux pouvoir eff-ify, quelque chose comme ceci:
name = 'Fred' age = 42 s = "My name is {name} and I am {age} years old" effify(s)
AFAIU, selon PEP 498 - Interpolation de chaînes littérales , ce n'est pas possible1. Il n'y a aucun moyen de créer par programmation une chaîne f:
Dans Python, une chaîne f est une chaîne littérale, préfixée par 'f', qui contient des expressions entre accolades .
1À moins bien sûr que vous ne souhaitiez utiliser quelque chose comme exec
comme @coldspeed l'a mentionné. Mais à ce stade, les inconvénients l'emportent probablement sur les avantages.
Une solution simple serait d'utiliser des chaînes f et eval.
def effify(non_f_str: str):
return eval(f'f"""{non_f_str}"""')
name = 'Fred'
age = 42
s = "My name is {name} and I am {age} years old"
effify(s)
'My name is Fred and I am 42 years old'
Cela ajoute essentiellement un "f" à la chaîne, puis évalue en tant que code. Les guillemets triples permettent également de prendre en charge les chaînes multilignes. La fonction essaiera d'extraire les variables référencées dans la chaîne f de la portée autour de son appel. Comme indiqué, l'utilisation de eval
peut être potentiellement dangereuse, mais si vous connaissez votre source, je pense que ce n'est pas plus dangereux que d'exécuter tout autre code.