Recherche…


Syntaxe

  • eval (expression [, globals = None [, locaux = None]])
  • exec (objet)
  • exec (objet, globales)
  • exec (objet, globales, locaux)

Paramètres

Argument Détails
expression Le code de l'expression sous la forme d'une chaîne ou d'un objet de code
object Le code d'instruction sous la forme d'une chaîne ou d'un objet de code
globals Le dictionnaire à utiliser pour les variables globales. Si les locaux ne sont pas spécifiés, cela est également utilisé pour les locaux. Si omis, les globals() de la portée appelante sont utilisés.
locals Un objet de mappage utilisé pour les variables locales. Si omis, celui passé pour les globals est utilisé à la place. Si les deux sont omis, les globals() et locals() de la portée d'appel sont utilisés respectivement pour les globals et les locals .

Remarques

Dans exec , si les globals sont des locals (c'est-à-dire qu'ils font référence au même objet), le code est exécuté comme s'il était au niveau du module. Si les globals et les locals sont des objets distincts, le code est exécuté comme s'il était dans un corps de classe .

Si l'objet globals est transmis mais ne spécifie pas la clé __builtins__ , les fonctions et les noms intégrés à Python sont automatiquement ajoutés à la portée globale. Pour supprimer la disponibilité des fonctions telles que l' print ou isinstance dans le cadre exécuté, laissez - globals ont la clé __builtins__ mis en correspondance avec la valeur None . Cependant, ce n'est pas une fonctionnalité de sécurité.

La syntaxe spécifique à Python 2 ne doit pas être utilisée; la syntaxe Python 3 fonctionnera dans Python 2. Ainsi, les formes suivantes sont obsolètes: <s>

  • exec object
  • exec object in globals
  • exec object in globals, locals

Évaluation des instructions avec exec

>>> code = """for i in range(5):\n    print('Hello world!')"""
>>> exec(code)
Hello world!
Hello world!
Hello world!
Hello world!
Hello world!

Evaluer une expression avec eval

>>> expression = '5 + 3 * a'
>>> a = 5
>>> result = eval(expression)
>>> result
20

Précompiler une expression pour l'évaluer plusieurs fois

compile fonction intégrée de compile peut être utilisée pour précompiler une expression dans un objet de code; Cet objet de code peut ensuite être passé à eval. Cela accélérera les exécutions répétées du code évalué. Le 3ème paramètre à compile doit être la chaîne 'eval' .

>>> code = compile('a * b + c', '<string>', 'eval')
>>> code
<code object <module> at 0x7f0e51a58830, file "<string>", line 1>
>>> a, b, c = 1, 2, 3
>>> eval(code)
5

Évaluation d'une expression avec eval à l'aide de globales personnalisés

>>> variables = {'a': 6, 'b': 7}
>>> eval('a * b', globals=variables)
42

En plus, le code ne peut pas se référer accidentellement aux noms définis à l'extérieur:

>>> eval('variables')
{'a': 6, 'b': 7}
>>> eval('variables', globals=variables)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'variables' is not defined

Utiliser defaultdict permet par exemple d'avoir des variables indéfinies définies à zéro:

>>> from collections import defaultdict
>>> variables = defaultdict(int, {'a': 42})
>>> eval('a * c', globals=variables)  # note that 'c' is not explicitly defined
0

Evaluer une chaîne contenant un littéral Python avec ast.literal_eval

Si vous avez une chaîne qui contient des littéraux Python, tels que des chaînes, des flottants, etc., vous pouvez utiliser ast.literal_eval pour évaluer sa valeur au lieu de eval . Cela a pour caractéristique supplémentaire de n'autoriser qu'une certaine syntaxe.

>>> import ast
>>> code = """(1, 2, {'foo': 'bar'})"""
>>> object = ast.literal_eval(code)
>>> object
(1, 2, {'foo': 'bar'})
>>> type(object)
<class 'tuple'>

Cependant, ceci n'est pas sécurisé pour l'exécution du code fourni par un utilisateur non fiable, et il est trivial d'interrompre un interpréteur avec une entrée soigneusement conçue.

>>> import ast
>>> ast.literal_eval('()' * 1000000)
[5]    21358 segmentation fault (core dumped)  python3

Ici, l'entrée est une chaîne de caractères () répétée un million de fois, ce qui provoque un blocage de l'analyseur CPython. Les développeurs CPython ne considèrent pas les bogues de l'analyseur comme des problèmes de sécurité.

Code d'exécution fourni par un utilisateur non approuvé à l'aide de exec, eval ou ast.literal_eval

Il n'est pas possible d'utiliser eval ou exec pour exécuter du code à partir d'utilisateurs non fiables en toute sécurité. Même ast.literal_eval est susceptible de se ast.literal_eval dans l'analyseur. Il est parfois possible de se prémunir contre l’exécution de code malveillant, mais cela n’exclut pas la possibilité d’un blocage brutal de l’analyseur ou du tokenizer.

Pour évaluer le code par un utilisateur non fiable, vous devez vous tourner vers un module tiers, ou peut-être écrire votre propre analyseur syntaxique et votre propre machine virtuelle en Python.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow