답변:
기본적으로 동적으로 생성 된 단일 Python 표현식 eval
을 평가 하는 exec
데 사용되며 실행 하는 데 사용됩니다. 부작용에 대해서만 동적으로 생성 된 Python 코드 .
eval
그리고 exec
이 두 가지 차이점이 있습니다 :
eval
만 받아들이는 하나의 표현 , exec
루프 : 파이썬 문이 코드 블록이 걸릴 수 try: except:
, class
및 기능 / 방법 def
등 initions하고 있습니다.
파이썬의 표현식은 변수 할당의 값으로 가질 수있는 것입니다.
a_variable = (anything you can put within these parentheses is an expression)
eval
주어진 표현식 의 값 을 반환하는 반면 exec
코드에서 반환 값을 무시하고 항상 반환합니다 None
(파이썬 2에서는 명령문이며 표현식으로 사용할 수 없으므로 실제로 아무것도 반환하지 않습니다).
버전 exec
1.0-2.7에서는 CPython exec
이 함수 내부의 부작용에 사용 된 함수에 대해 다른 종류의 코드 오브젝트를 생성해야했기 때문에 명령문이었습니다 .
파이썬 3에서는 exec
함수입니다. 사용되는 함수의 컴파일 된 바이트 코드에는 영향을 미치지 않습니다.
따라서 기본적으로 :
>>> a = 5
>>> eval('37 + a') # it is an expression
42
>>> exec('37 + a') # it is an expression statement; value is ignored (None is returned)
>>> exec('a = 47') # modify a global variable as a side effect
>>> a
47
>>> eval('a = 47') # you cannot evaluate a statement
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1
a = 47
^
SyntaxError: invalid syntax
compile
의 'exec'
모드는 바이트 코드로 문의 수를 컴파일하는 암시 적으로 항상 반환 None
에있는 반면, 'eval'
모드 그것은 컴파일 한 바이트 코드로 표현이 반환 하는 식의 값.
>>> eval(compile('42', '<string>', 'exec')) # code returns None
>>> eval(compile('42', '<string>', 'eval')) # code returns 42
42
>>> exec(compile('42', '<string>', 'eval')) # code returns 42,
>>> # but ignored by exec
에서 'eval'
합니다 (에 따라서 모드 eval
문자열이 전달되면 기능)는이 compile
소스 코드를 진술 또는 하나의 표현을 넘어 다른 것을 포함 된 경우 예외가 발생 :
>>> compile('for i in range(3): print(i)', '<string>', 'eval')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1
for i in range(3): print(i)
^
SyntaxError: invalid syntax
실제로 "eval은 단일 표현식 만 허용 합니다 " 라는 문장 은 문자열 (Python 소스 코드 를 포함 )이 전달 될 때만 적용됩니다 eval
. 그런 다음 compile(source, '<string>', 'eval')
이를 사용하여 내부적으로 바이트 코드로 컴파일됩니다 .
경우 code
(파이썬 포함 개체 바이트 코드가 )에 전달 exec
하거나 eval
, 그들은 동일하게 작동 사실을 제외하고, exec
아직 반환, 반환 값을 무시 None
항상. 따라서 문자열로 전달하지 않고 바이트 코드로 코드를 eval
작성하면 명령문이있는 것을 실행할 수 있습니다 compile
.
>>> eval(compile('if 1: print("Hello")', '<string>', 'exec'))
Hello
>>>
컴파일 된 코드에 문이 포함되어 있어도 문제없이 작동합니다. 이것은 None
에서 반환 된 코드 객체의 반환 값이므로 여전히 반환합니다 compile
.
에서 'eval'
합니다 (에 따라서 모드 eval
문자열이 전달되면 기능)는이 compile
소스 코드를 진술 또는 하나의 표현을 넘어 다른 것을 포함 된 경우 예외가 발생 :
>>> compile('for i in range(3): print(i)', '<string>'. 'eval')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1
for i in range(3): print(i)
^
SyntaxError: invalid syntax
exec
과 eval
이 exec
함수 ( Python 2의 명령문 )는 동적으로 작성된 명령문 또는 프로그램을 실행하는 데 사용됩니다.
>>> program = '''
for i in range(3):
print("Python is cool")
'''
>>> exec(program)
Python is cool
Python is cool
Python is cool
>>>
eval
함수는에 대해 동일한 않는 하나의 표현 , 그리고 표현의 값을 반환합니다 :
>>> a = 2
>>> my_calculation = '42 * a'
>>> result = eval(my_calculation)
>>> result
84
exec
그리고 eval
둘 다 프로그램 / 표현식이 str
, unicode
또는 bytes
소스 코드 를 포함 하는 code
객체 또는 Python 바이트 코드를 포함 하는 객체 로 실행되도록 허용합니다 .
경우 str
/ unicode
/ bytes
포함 된 소스 코드에 전달 exec
, 그것은에 동등하게 동작합니다
exec(compile(source, '<string>', 'exec'))
와 eval
유사하게 상응하는 동작 :
eval(compile(source, '<string>', 'eval'))
모든 표현식은 파이썬에서 명령문으로 사용될 수 있기 때문에 ( Expr
파이썬 추상 문법 에서는 노드 라고 불리며 반대는 사실이 아닙니다), exec
반환 값이 필요하지 않은 경우 언제든지 사용할 수 있습니다 . 말 즉, 당신도 사용할 수 있습니다 eval('my_func(42)')
또는 exec('my_func(42)')
, 그 존재의 차이 eval
값에 의해 반환 반환 my_func
및 exec
폐기를 :
>>> def my_func(arg):
... print("Called with %d" % arg)
... return arg * 2
...
>>> exec('my_func(42)')
Called with 42
>>> eval('my_func(42)')
Called with 42
84
>>>
2 중, 단지 exec
문을 포함 소스 코드를 받아 같은 def
, for
, while
, import
, 또는 class
, 할당 문 (일명 a = 42
), 또는 전체 프로그램 :
>>> exec('for i in range(3): print(i)')
0
1
2
>>> eval('for i in range(3): print(i)')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1
for i in range(3): print(i)
^
SyntaxError: invalid syntax
둘 다 exec
와 eval
- 2 개 개의 추가 위치 인수 동의 globals
와 locals
- 글로벌 및 로컬 변수는 코드가 보는 것을 스코프입니다. 받는 이러한 기본 globals()
과 locals()
라고하는 범위 내에서 exec
또는 eval
, 그러나 어떤 사전을 사용할 수에 대한 globals
어떤 mapping
위해 locals
(포함 dict
물론). 이것들은 코드가 보는 변수를 제한 / 수정하는 데 사용될뿐만 아니라 종종 exec
uted 코드가 생성 하는 변수를 캡처하는 데에도 사용됩니다 :
>>> g = dict()
>>> l = dict()
>>> exec('global a; a, b = 123, 42', g, l)
>>> g['a']
123
>>> l
{'b': 42}
당신이 전체의 값을 표시하는 경우 ( g
, 훨씬 더 길어질 수 있기 때문에 것입니다 exec
및 eval
내장 기능과 같이 모듈 추가__builtins__
가없는 경우 자동 전역에).
Python 2에서 exec
명령문 의 공식 구문 은 실제로 다음 exec code in globals, locals
과 같습니다.
>>> exec 'global a; a, b = 123, 42' in g, l
그러나 대체 구문 exec(code, globals, locals)
도 항상 허용되었습니다 (아래 참조).
compile
compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
내장과 같은 코드의 반복 호출을 빠르게 할 수 있습니다 exec
또는 eval
에 소스를 컴파일하여 code
사전 객체입니다. 이 mode
매개 변수는 compile
함수가 받아들이는 코드 조각 종류와 생성하는 바이트 코드 종류를 제어합니다. 선택 사항은 'eval'
, 'exec'
및 'single'
:
'eval'
mode는 단일 표현식을 기대하며, 실행될 때 해당 표현식 의 값을 리턴하는 바이트 코드를 생성 합니다 .
>>> dis.dis(compile('a + b', '<string>', 'eval'))
1 0 LOAD_NAME 0 (a)
3 LOAD_NAME 1 (b)
6 BINARY_ADD
7 RETURN_VALUE
'exec'
단일 표현식에서 전체 코드 모듈에 이르는 모든 종류의 파이썬 구성을 허용하고 마치 모듈 최상위 문장처럼 실행합니다. 코드 객체는 None
다음을 반환합니다 .
>>> dis.dis(compile('a + b', '<string>', 'exec'))
1 0 LOAD_NAME 0 (a)
3 LOAD_NAME 1 (b)
6 BINARY_ADD
7 POP_TOP <- discard result
8 LOAD_CONST 0 (None) <- load None on stack
11 RETURN_VALUE <- return top of stack
'single'
제한된 형태 'exec'
포함하는 소스 코드를 허용하는 단일 (의해 분리 또는 여러 문장 문장 ;
마지막 문 발현 문장 인 경우)에, 생성 된 바이트 코드는 지문 repr
표준 출력이 식의 값을 (!) .
if
- elif
- else
체인과 루프 else
, 그리고 try
그와 함께 except
, else
그리고 finally
블록은 하나의 문으로 간주됩니다.
'single'
파이썬 2에서는 때때로 코드에 여러 개의 최상위 문장을 허용 하는 버그가 있다는 점을 제외하고 2 개의 최상위 문장을 포함하는 소스 프래그먼트는 에러입니다 . 첫 번째 만 컴파일됩니다. 나머지는 무시됩니다.
Python 2.7.8에서 :
>>> exec(compile('a = 5\na = 6', '<string>', 'single'))
>>> a
5
그리고 파이썬 3.4.2에서 :
>>> exec(compile('a = 5\na = 6', '<string>', 'single'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1
a = 5
^
SyntaxError: multiple statements found while compiling a single statement
이것은 대화 형 파이썬 쉘을 만드는 데 매우 유용합니다. 그러나 결과 코드가 있더라도 표현식의 값은 반환되지 않습니다eval
.
따라서 최대의 구분 exec
및 eval
실제로는에서 온다 compile
기능과 모드.
소스 코드를 바이트 코드로 컴파일하는 것 외에도 추상 구문 트리 (Python 코드의 구문 분석 트리)를 객체 로 compile
컴파일하는 기능을 지원 합니다. 소스 코드를 추상 구문 트리로 변환합니다 ( Python으로 작성되고을 호출 함 ). 예를 들어 소스 코드를 즉석에서 수정하고 동적 코드를 생성하는 데 사용됩니다. 복잡한 경우에는 텍스트 줄 대신 노드 트리로 코드를 처리하는 것이 더 쉽기 때문입니다.code
ast.parse
compile(source, filename, mode, PyCF_ONLY_AST)
동안 eval
만 당신이 하나의 식을 포함하는 문자열을 평가할 수 있습니다, 당신이 할 수있는 eval
전체 문장이나 된 경우에도 전체 모듈 compile
바이트 코드로 거라고; 즉, Python 2에서는 print
문장이며 eval
직접적 으로 이끌 수 없습니다 .
>>> eval('for i in range(3): print("Python is cool")')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1
for i in range(3): print("Python is cool")
^
SyntaxError: invalid syntax
compile
그것으로 'exec'
로 모드 code
객체와 당신은 할 수 eval
그것을 ; 이 eval
함수는을 반환 None
합니다.
>>> code = compile('for i in range(3): print("Python is cool")',
'foo.py', 'exec')
>>> eval(code)
Python is cool
Python is cool
Python is cool
로 한 외모 경우 eval
와 exec
CPython의 3 소스 코드, 이것은 매우 분명하다; 둘 다 PyEval_EvalCode
동일한 인수를 사용하여 exec
명시 적으로 반환None
하는 유일한 차이점 입니다.
exec
Python 2와 Python 3 의 구문 차이파이썬의 주요 차이점 중 하나 (2) 즉 exec
진술하고 eval
있는 내장 기능 (모두 내장되어 기능 파이썬 3). exec
파이썬 2 의 공식 구문은 다음 과 같습니다 exec code [in globals[, locals]]
.
파이썬 2 대 3의 대다수는 달리 포팅 가이드가 보인다 제안 은 exec
CPython과 2 문은 또한 구문을 사용할 수 있습니다 외모 정확히 등 exec
파이썬 3에서 함수 호출 파이썬 0.9.9가 있었다 이유는 것을 exec(code, globals, locals)
내장을 기능적으로! 그리고 내장 함수는 Python 1.0 릴리스 이전의exec
문장 으로 대체 되었습니다 .
이 파이썬 0.9.9와 이전 버전과의 호환성을 아프게하지하는 것이 바람직 이었기 때문에, 귀도 반 로섬 (Guido van Rossum)은 1993 년에 호환성 해킹을 추가 한 다음이 경우 code
길이가 2 또는 3의 튜플이고, globals
그리고 locals
에 전달되지 않은 exec
가, 그렇지 않으면 문 code
해석됩니다 것처럼 튜플의 2 층과 3 요소는했다 globals
및 locals
각각. 호환성 1.4 는 Python 1.4 문서 (가장 빠른 온라인 버전) 에서도 언급되지 않았습니다 . 따라서 포팅 가이드 및 도구의 많은 작가들에게 2012 년 11 월에 다시 문서화 될 때까지 알려지지 않았습니다 .
첫 번째 표현은 길이 2 또는 3의 튜플 일 수도 있습니다.이 경우 선택적 부분을 생략해야합니다. 양식
exec(expr, globals)
은와 동일exec expr in globals
하지만 양식exec(expr, globals, locals)
은와 같습니다exec expr in globals, locals
. 튜플 형식은 명령문이 아닌 함수 인exec
Python 3과의 호환성 을 제공exec
합니다.
그렇습니다. CPython 2.7에서는 실제로 20 년 동안 이전 버전과의 호환성을 위해 존재했을 때, 이전 버전과의 호환성 옵션 (이전 버전과의 호환성 옵션이있는 사람들을 혼동하는 이유)을 언급했습니다 .
따라서 while exec
은 Python 1 및 Python 2의 명령문이고 Python 3 및 Python 0.9.9의 내장 함수입니다.
>>> exec("print(a)", globals(), {'a': 42})
42
널리 배포 된 모든 Python 버전에서 동일한 동작을 수행했습니다. 그리고 Jython 2.5.2, PyPy 2.3.1 (Python 2.7.6) 및 IronPython 2.6.1에서도 작동합니다 (CPython의 문서화되지 않은 동작에 밀접하게 적용됩니다).
호환성 해킹으로 Pythons 1.0-2.7에서 할 수없는 것은 반환 값을 exec
변수 에 저장하는 것입니다 .
Python 2.7.11+ (default, Apr 17 2016, 14:00:29)
[GCC 5.3.1 20160413] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> a = exec('print(42)')
File "<stdin>", line 1
a = exec('print(42)')
^
SyntaxError: invalid syntax
( exec
항상을 반환하는 것처럼 Python 3에서는 유용하지 않습니다 None
) 또는에 대한 참조를 전달하십시오 exec
.
>>> call_later(exec, 'print(42)', delay=1000)
File "<stdin>", line 1
call_later(exec, 'print(42)', delay=1000)
^
SyntaxError: invalid syntax
가능성이 거의 없지만 누군가가 실제로 사용한 패턴은 무엇입니까?
또는 목록 이해에 사용하십시오.
>>> [exec(i) for i in ['print(42)', 'print(foo)']
File "<stdin>", line 1
[exec(i) for i in ['print(42)', 'print(foo)']
^
SyntaxError: invalid syntax
이것은 목록 이해의 남용입니다 ( for
루프를 대신 사용하십시오!).
42
또한 표현식이므로 @
데코레이터로 사용할 수 없습니다 .
decorator ::= "@" dotted_name ["(" [parameter_list [","]] ")"] NEWLINE
. 즉, 임의의 표현식을 데코레이터로 사용할 수 없으며, 점으로 구분되는 식별자와 선택적 호출 인수 만 사용할 수 있습니다.
a = b = c
오른쪽 b = c
은 표현식이 아닌 완벽하게 유효한 명령문 입니다.
exec
파이썬 2.x의 문장과 파이썬 3.x의 함수는 표현이 아닙니다. 문자열에 포함 된 명령문 또는 명령문 세트를 컴파일하고 즉시 평가합니다. 예:
exec('print(5)') # prints 5.
# exec 'print 5' if you use Python 2.x, nor the exec neither the print is a function there
exec('print(5)\nprint(6)') # prints 5{newline}6.
exec('if True: print(6)') # prints 6.
exec('5') # does nothing and returns nothing.
eval
내장 기능 (이다 없는 표현 반환 식을 생산하는 가치를 평가하는 문). 예:
x = eval('5') # x <- 5
x = eval('%d + 6' % x) # x <- 11
x = eval('abs(%d)' % -100) # x <- 100
x = eval('x = 5') # INVALID; assignment is not an expression.
x = eval('if 1: x = 4') # INVALID; if is a statement, not an expression.
compile
exec
및 의 하위 버전입니다 eval
. 명령문이나 표현식을 실행하거나 평가하지 않지만이를 수행 할 수있는 코드 오브젝트를 리턴합니다. 모드는 다음과 같습니다.
compile(string, '', 'eval')
수행 한 코드 객체를 반환합니다 eval(string)
. 당신이주의 할 수없는 이 모드에서 문을 사용; (단일) 표현식 만 유효합니다.compile(string, '', 'exec')
수행 한 코드 객체를 반환합니다 exec(string)
. 여기에서 원하는 수의 문장을 사용할 수 있습니다.compile(string, '', 'single')
등이다 exec
모드,하지만 첫 번째 문을 제외한 모든 것을 무시합니다. 결과가 포함 된 if
/ else
문은 단일 문으로 간주됩니다.exec()
이제는 실제로 함수입니다.
exec
당신이 목표로하고있는 버전의 진술 이기 때문에, 그러한 괄호를 포함시키는 것은 기만적이며,을 사용하려고하면 in globals, locals
버그도 있습니다.
exec
은 괄호와 파이썬 2의 호출과 같은 기능을 지원합니다 .
x = (y)
사실 일 수도 있습니다. 또 다른 문장 전환 기능은 print
; print(1, 2, 3)
파이썬 2와 3 의 결과를 비교하십시오.
exec는 진술 용이며 아무것도 반환하지 않습니다. eval은 표현 식용이며 expression의 값을 리턴합니다.
표현은 "무언가"를 의미하고 진술은 "무언가"를 의미합니다.
[i for i in globals().values() if hasattr(i, '__call__')][0]
문장이나 표현은? 그것이 표현이라면 왜@
데코레이터로 사용할 수 없습니까?