수색…


통사론

  • eval (expression [, globals = None [, locals = None]])
  • exec (객체)
  • exec (객체, 전역)
  • exec (객체, 전역, 지역)

매개 변수

논의 세부
expression 표현식 코드를 문자열 또는 code 객체
object 명령문 코드를 문자열 또는 code 객체
globals 전역 변수에 사용할 사전입니다. 지역을 지정하지 않으면 지역 주민에게도 사용됩니다. 생략하면 호출 영역의 globals() 가 사용됩니다.
locals 로컬 변수에 사용되는 매핑 객체입니다. 생략하면 globals 에 대해 전달 된 값이 대신 사용됩니다. 둘 다 생략되면 호출 범위의 globals()locals()globalslocals 각각 사용됩니다.

비고

exec 에서 globalslocals 인 경우 (즉, 동일한 객체를 참조하는 경우) 코드는 모듈 수준에있는 것처럼 실행됩니다. globalslocals globals 가 다른 객체 인 경우 코드는 클래스 본문 에있는 것처럼 실행됩니다.

globals 객체가 전달되었지만 __builtins__ 키가 지정되어 있지 않으면 Python 기본 제공 함수와 이름이 자동으로 전역 범위에 추가됩니다. 같은 함수의 가용성 억제하기 위해 print 또는 isinstance 실행 된 범위를하자 globals 키가 __builtins__ 중시하지 매핑 None . 그러나 이것은 보안 기능이 아닙니다.

파이썬 2 특정 구문을 사용하면 안됩니다. 파이썬 3 구문은 파이썬 2에서 작동합니다. 따라서 다음 형식은 더 이상 사용되지 않습니다 : <s>

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

exec로 문장 평가하기

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

eval로 표현식 평가하기

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

표현식을 여러 번 평가하기 위해 프리 컴파일

compile 내장 함수는 코드 오브젝트에 표현식을 프리 D 파일하는 데 사용할 수 있습니다. 이 코드 객체는 eval에 전달 될 수 있습니다. 이렇게하면 평가 된 코드가 반복적으로 실행됩니다. compile 세 번째 매개 변수는 '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

맞춤 전역을 사용하여 eval로 표현식 평가하기

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

더하기,이 코드는 실수로 외부에서 정의 된 이름을 참조 할 수 없습니다.

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

defaultdict 사용하면 예를 들어 정의되지 않은 변수를 0으로 설정할 수 있습니다.

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

ast.literal_eval을 사용하여 파이썬 리터럴을 포함하는 문자열 평가

문자열, 부동 소수점 등의 파이썬 리터럴을 포함하는 문자열이있는 경우 ast.literal_eval 을 사용하여 eval 대신 값을 평가할 수 있습니다. 이것은 특정 구문만을 허용하는 추가 기능을 가지고 있습니다.

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

그러나이 방법은 신뢰할 수없는 사용자가 제공 한 코드를 실행하는 데 안전하지 않으며주의 깊게 작성된 입력을 사용하여 통역사를 다운시키는 것도 쉽지 않습니다.

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

여기서 입력의 문자열 () CPython의 파서에서 충돌이 발생 백만 번 반복은. CPython 개발자는 파서의 버그를 보안 문제로 간주하지 않습니다.

exec, eval 또는 ast.literal_eval을 사용하여 신뢰할 수없는 사용자가 제공 한 코드 실행

신뢰할 수없는 사용자의 코드를 eval 또는 exec 를 사용하여 안전하게 실행할 수 없습니다. 심지어 ast.literal_eval 은 파서에서 충돌하는 경향이 있습니다. 때로는 악의적 인 코드 실행을 막는 것이 가능하지만 파서 또는 토크 나이저에서 명백한 충돌 가능성을 배제하지 않습니다.

신뢰할 수없는 사용자가 코드를 평가하려면 타사 모듈로 전환하거나 Python으로 자체 파서와 자체 가상 머신을 작성해야합니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow