Que fait eval() de Python?

Dans le livre que je lis sur Python, il continue à utiliser le code eval(input('blah'))

J'ai lu la documentation, et je la comprends, mais je ne vois toujours pas comment cela change la fonction input().

Que fait-il? Quelqu'un peut m'expliquer?

198
demandé sur BYS2 2012-02-21 23:19:16

9 réponses

La fonction eval permet à un programme Python d'exécuter du code Python en lui-même.

Exemple D'évaluation (shell interactif):

>>> x = 1
>>> eval('x + 1')
2
>>> eval('x')
1
191
répondu BYS2 2018-06-12 21:03:50

eval() interprète une chaîne en tant que code. La raison pour laquelle tant de gens vous ont averti de l'utiliser est parce qu'un utilisateur peut l'utiliser comme une option pour exécuter du code sur l'ordinateur. Si vous avez eval(input()) et os importés, une personne peut entrer input() os.system('rm -R *') ce qui supprimerait tous vos fichiers dans votre répertoire personnel. (En supposant que vous avez un système unix). L'utilisation de eval() est un trou de sécurité. Si vous avez besoin de convertir des chaînes vers d'autres formats, essayez d'utiliser des choses qui le font, comme int().

117
répondu CoffeeRain 2012-02-21 19:39:26

En Python 2.x input(...) est équivalent à eval(raw_input(...)), en Python 3.x {[2] } a été renommé input, ce qui, je pense, conduit à votre confusion (vous regardiez probablement la documentation de input en Python 2.x). De plus, eval(input(...)) fonctionnerait bien en Python 3.x, mais soulèverait un TypeError en Python 2.

Dans ce cas, eval est utilisé pour forcer la chaîne renvoyée par input dans une expression et interprétée. Généralement, cela est considéré comme une mauvaise pratique.

26
répondu zeekay 2012-02-21 20:02:03

Beaucoup de bonnes réponses ici, mais aucun décrire l'utilisation de eval, dans le cadre de ses globals= et locals= kwargs. Ceux - ci peuvent être utilisés pour limiter les méthodes disponibles via la méthode eval. Par exemple, si vous chargez un nouvel interpréteur python, locals() et globals() seront les mêmes et ressembleront à ceci:

>>> globals()
{'__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__doc__': None,
 '__spec__': None, '__builtins__': <module 'builtins' (built-in)>,
 '__package__': None, '__name__': '__main__'}

Il existe certainement des méthodes dans le module builtins qui peuvent causer des dommages importants à un système. Mais il est possible de bloquer quoi que ce soit et tout ce que nous ne veux pas disponible. Prenons un exemple. Disons que nous voulons construire une liste pour représenter un domaine des cœurs disponibles sur un système. Pour moi, j'ai 8 cœurs donc je voudrais une liste [1, 8].

>>>from os import cpu_count()
>>>eval('[1, cpu_count()'])
[1, 8]

De même, tout __builtins__ est disponible.

>>>eval('abs(-1)')
1

Ok. Nous voyons donc une méthode que nous voulons exposée et un exemple d'une méthode (parmi beaucoup qui peut être beaucoup plus insidieuse) que nous ne voulons pas exposée. Alors permet de tout bloquer.

>>>eval('[1, cpu_count()]', {'__builtins__':None}, {})
TypeError: 'NoneType' object is not subscriptable

Nous avons effectivement bloqué tous les __builtins__ méthodes et en tant que tel a apporté un niveau de protection dans notre système. À ce stade, nous pouvons commencer à ajouter de nouveau dans les méthodes que nous voulons exposés.

>>>from os import cpu_count
>>>exposed_methods = {'cpu_count': cpu_count}
>>>eval('cpu_count()', {'__builtins__':None}, exposed_methods)
8
>>>eval('abs(cpu_count())', {'__builtins__':None}, exposed_methods)
TypeError: 'NoneType' object is not subscriptable

Maintenant, nous avons la méthode cpu_count disponible tout en bloquant tout ce que nous ne voulons pas. À mon avis, c'est super puissant et clairement de la portée des autres réponses pas une implémentation commune. Il y a de nombreuses utilisations pour quelque chose comme ça et tant qu'il est géré correctement, je pense personnellement que eval peut être en toute sécurité utilisé à une grande valeur.

N. B.

Quelque chose d'autre qui est cool à propos de ces kwargs est que vous pouvez commencer à utiliser un raccourci pour votre code. Disons que vous utilisez eval dans le cadre d'un pipeline pour exécuter du texte importé. Le texte n'a pas besoin d'avoir du code exact, il peut suivre un format de fichier de modèle, et toujours exécuter tout ce que vous voulez. Par exemple:

>>>from os import cpu_count
>>>eval('[1,cores]', {'__builtins__': None}, {'cores': cpu_count()})
[1, 8]
18
répondu Grr 2017-04-27 20:22:26

eval() évalue la chaîne passée en tant qu'expression Python et renvoie le résultat. Par exemple, eval("1 + 1") interprète et exécute l'expression "1 + 1" et renvoie le résultat (2).

Une des raisons pour lesquelles vous pourriez être confus est que le code que vous avez cité implique un niveau d'indirection. L'appel de fonction interne (entrée) est exécuté en premier afin que l'utilisateur voit l'invite "blah". Imaginons qu'ils répondent avec "1 + 1" (citations ajoutées pour plus de clarté, ne les Tapez pas lors de l'exécution de votre programme), l'entrée la fonction retourne cette chaîne, qui est ensuite transmis à la fonction externe (eval) qui interprète la chaîne et renvoie le résultat (2).

Lire plus sur eval ici.

6
répondu Marc Cohen 2018-06-12 21:08:28

eval(), comme son nom l'indique, évalue l'argument passé.

raw_input() est maintenant input() en python 3.X versions. Ainsi, l'exemple le plus couramment trouvé pour l'utilisation de eval() est son utilisation pour fournir la fonctionnalité que input() a fournie dans 2.X version de python. raw_input renvoie les données saisies par l'utilisateur sous forme de chaîne, tandis que input évalue la valeur des données saisies et les renvoie.

eval(input("bla bla")) reproduit ainsi la fonctionnalité de input() dans 2.x, c'est-à-dire d'évaluer les données saisies par l'utilisateur.

En bref: eval() évalue les arguments qui lui sont passés et donc eval('1 + 1') renvoie 2.

5
répondu Rubal 2018-06-12 21:08:54

Peut-être un exemple trompeur de lecture d'une ligne et de son interprétation.

Essayez eval(input()) et tapez "1+1" - cela devrait imprimer 2. Eval évalue les expressions.

4
répondu hburde 2015-08-25 13:26:18

L'une des applications utiles de eval() est d'évaluer les expressions python à partir de la chaîne. Par exemple, Charger à partir d'une représentation de chaîne de fichier du dictionnaire:

running_params = {"Greeting":"Hello "}

fout = open("params.dat",'w')

fout.write(repr(running_params))

fout.close()

Lisez - le en tant que variable et modifiez-le:

fin = open("params.dat",'r')

diction=eval(fin.read())

diction["Greeting"]+="world"

fin.close()

print diction

Sortie:

{'Greeting': 'Hello world'}
4
répondu Nikolay Frick 2018-06-12 21:09:16

Je suis en retard pour répondre à cette question mais, personne ne semble donner une réponse claire à la question.

Si un utilisateur entre une valeur numérique, input() renverra une chaîne.

>>> input('Enter a number: ')
Enter a number: 3
>>> '3'
>>> input('Enter a number: ')
Enter a number: 1+1
'1+1'

Donc, eval() évaluera la valeur retournée (ou l'expression) qui est une chaîne et retournera un entier / flottant.

>>> eval(input('Enter a number: '))
Enter a number: 1+1
2
>>> 
>>> eval(input('Enter a number: '))
Enter a number: 3.14
3.14

Bien sûr, c'est une mauvaise pratique. int() ou float() doit être utilisé à la place de eval() dans ce cas.

>>> float(input('Enter a number: '))
Enter a number: 3.14
3.14
2
répondu Calvin Kim 2018-06-13 06:11:08