Szukaj…


Składnia

  • eval (wyrażenie [, globals = None [, locals = None]])
  • exec (obiekt)
  • exec (obiekt, globale)
  • exec (obiekt, globale, lokalni)

Parametry

Argument Detale
expression Kod wyrażenia jako ciąg znaków lub obiekt code
object Kod instrukcji jako ciąg znaków lub obiekt code
globals Słownik używany dla zmiennych globalnych. Jeśli nie określono miejscowych, jest to również używane w przypadku miejscowych. Jeśli pominięto, używane są globals() zakresu wywoływania.
locals Obiekt odwzorowania używany dla zmiennych lokalnych. Jeśli zostanie pominięty, używany jest ten przekazany dla globals . Jeśli oba zostaną pominięte, wówczas globals() i locals() zakresu wywoływania są używane odpowiednio dla globals i locals .

Uwagi

W exec , jeśli globalslocals (tj. Odnoszą się do tego samego obiektu), kod jest wykonywany tak, jakby znajdował się na poziomie modułu. Jeśli globals i locals są odrębnymi obiektami, kod jest wykonywany tak, jakby był w treści klasy .

Jeśli obiekt globals jest przekazywany, ale nie określa klucza __builtins__ , wówczas wbudowane funkcje i nazwy Pythona są automatycznie dodawane do zakresu globalnego. Aby stłumić dostępności funkcji takich jak print lub isinstance w zakresie wykonywanego niech globals mają kluczową __builtins__ odwzorowaną na wartość None . Nie jest to jednak funkcja bezpieczeństwa.

Nie należy używać składni specyficznej dla języka Python 2; składnia Python 3 będzie działać w Pythonie 2. Dlatego następujące formy są nieaktualne: <s>

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

Ocena instrukcji za pomocą exec

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

Ocena wyrażenia za pomocą eval

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

Wstępna kompilacja wyrażenia w celu oceny go wiele razy

wbudowanej funkcji compile można użyć do wstępnej kompilacji wyrażenia do obiektu kodu; ten obiekt kodu można następnie przekazać do eval. Przyspieszy to wielokrotne wykonywanie analizowanego kodu. Trzecim parametrem do compile musi być ciąg '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

Ocena wyrażenia za pomocą eval przy użyciu niestandardowych globałów

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

Dodatkowo, kod nie może przypadkowo odwoływać się do nazw zdefiniowanych na zewnątrz:

>>> 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

Użycie defaultdict pozwala na przykład ustawić niezdefiniowane zmienne na zero:

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

Ocena ciągu zawierającego literał w języku Python za pomocą ast.literal_eval

Jeśli masz ciąg znaków, który zawiera literały w języku Python, takie jak ciągi, ast.literal_eval itp., Możesz użyć ast.literal_eval do oceny jego wartości zamiast wartości eval . Ma to dodatkową funkcję pozwalającą tylko na określoną składnię.

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

Nie jest to jednak bezpieczne przy wykonywaniu kodu dostarczonego przez niezaufanego użytkownika, a zawieszenie interpretera przy starannie spreparowanym wejściu jest trywialne

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

Tutaj dane wejściowe to ciąg () powtórzony milion razy, co powoduje awarię parsera CPython. Programiści CPython nie uważają błędów w parserze za kwestie bezpieczeństwa.

Wykonywanie kodu dostarczonego przez niezaufanego użytkownika za pomocą exec, eval lub ast.literal_eval

Nie jest możliwe użycie eval lub exec do bezpiecznego wykonania kodu od niezaufanego użytkownika. Nawet ast.literal_eval jest podatny na awarie w parserze. Czasami można zabezpieczyć się przed złośliwym wykonaniem kodu, ale nie wyklucza to możliwości bezwarunkowych awarii w parserze lub tokenizerze.

Aby ocenić kod przez niezaufanego użytkownika, musisz zwrócić się do jakiegoś modułu innej firmy lub napisać własny parser i własną maszynę wirtualną w Pythonie.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow