评估,执行和编译之间的区别是什么?
我一直在研究Python代码的动态评估,并访问 eval()
和 compile()
函数,以及 exec
语句。
有人可以解释 eval
和 exec
以及 compile()
的不同模式如何适合 exec exec 之间的区别吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
简短的答案或tl; dr
基本上是 evary> evary < << /a>用于 eval uate单个动态生成的python表达式,
exec
用于 exec ute仅用于其副作用,动态生成的python代码。evary
和exec
有这两个区别:eval
仅接受单个表达式,exec
可以采用具有python语句的代码块:loops,尝试:excesef:
,class
and function/methoddef
def initions and and code>很快。python中的一个表达式是您可以拥有的变量分配中的值:
eval
返回给定表达式的值,而exec 忽略从其代码中的返回值,并且始终返回
none
(在Python 2中,这是一个语句,不能用作表达式,因此它确实不会返回任何内容)。在版本1.0-2.7中,
exec
是一个语句,因为CPYTHON需要为使用exec
在功能中使用exec
的函数产生其他类型的代码对象。在Python 3中,
exec
是一个函数;它的使用对使用函数的编译字节码没有影响。因此,基本上是:
compile
在'exec'
mode中,将任何数量的语句编译成一个字节,隐含地始终返回中'eval'
模式,它将单个表达式编译到字节码中,返回该表达式的值。在
'eval'
模式下代码包含语句或单个表达式以外的其他内容:实际上语句“ eval仅接受单个表达式” 仅在传递字符串(包含Python source代码)时才适用到
评估
。然后使用“ noreferrer”>compile(source,'&gt&gt&gt&gt&gt; ;','eval')
这是差异真正来自的地方。如果
代码
对象(其中包含Python bytecode )将传递给exec
或ext
,他们的行为相同的,除了exec
忽略返回值以下事实外,仍然返回none
总是。 则可以使用eval
执行具有语句的内容因此,如果您只是
compile
d , 编译的代码包含语句。它仍然返回无
,因为这是从compile
返回的代码对象的返回值。在
'eval'
模式下代码包含语句或单个表达式以外的其他任何内容:答案越长,又称gory详细信息
exec
和eval
exec
函数( python 2中的语句用于执行动态创建的语句或程序:evary
函数对a 单个表达式,和返回表达式的值:exec
andest
既接受要运行的程序/表达式代码
对象包含Python字节码。如果
str
/unicode
/bytes
包含源代码的传递给exec
代码>评估类似的行为等同于:
由于所有表达式都可以用作Python中的语句(这些称为
expr
python 摘要语法;相反的是不正确的),您可以随时使用exec
,如果不需要返回值。也就是说,您可以使用eval('my_func(42)')
或exec('my_func(42)')
,区别在于> deal
返回my_func
返回的值,exec
dovers it:of 2,仅
exec
接受包含语句的源代码,例如def
,, while ,, import ,或class
,分配语句(akaa = 42
)或整个程序:exec
和evar> eval
接受2个附加位置参数 -globals
和当地人
- 是代码看到的全局和本地变量范围。这些默认为globals()
和locals()
在称为exec
或eval
的范围内字典可用于Globals
和任何映射
当地人
(当然包括dict
)。这些不仅可以用来限制/修改代码看到的变量,而且通常也用于捕获exec
uted代码创建的变量:(如果您显示整个<的值代码> g ,它将更长的时间,因为
exec
和eval
将内置模块添加为______enins ____________________
如果丢失了)。在Python 2中,
exec
语句的官方语法实际上是exec code in Globals,locals
,如在替代语法
exec(代码,全球范围,当地人,当地人) )
也一直被接受(见下文)。compile
compile> compile(source,filename,filename,mode,mode,mode ,flags = 0,dont_inherit = false,optimize = -1)
可以使用内置的内置 - 用exec
或加快相同代码的重复调用通过将源汇编为
。代码
对象,请评估模式
参数控制代码片段的种类compile
函数接受以及它产生的字节码的种类。选择是'eval'
,'exec'
和'single'
:'eval'eval'
模式期望单个表达式,并会产生字节码,即运行将返回的值,该表达式:<代码>'exec'接受从单个表达式到整个代码模块的任何类型的python构造,并像模块上的顶级语句一样执行它们。代码对象返回
无
:'单'
是'exec'exec'
的有限形式,它接受包含单个语句(或由;
分隔的多个语句)如果最后一个语句是表达式语句,则结果字节也 也打印了repr
该表达式对标准输出的值(!)。一个如果 -
elif
-else
链,带有else> else
的环,尝试<
/code>及其
和除外
,<代码> else最后
块被视为一个单个语句。一个包含2个顶级语句的源片段是
'single''
的错误代码;只有第一个是编译的;其余的被忽略:在Python 2.7.8:
中
和python 3.4.2:
这对于制作交互式Python壳非常有用。但是,即使您
eval> eval
,表达式的值是未返回的因此,
exec
和eval
的最大区别实际上来自compile
函数及其模式。除了将源代码编译到字节码外,
编译
支持编译 抽象的语法树 (Python代码的解析树)中代码
对象;将源代码和抽象语法树(ast.parse
>编写为python),只需调用compile(source,filename,mode,pycf_only_ast)
));例如,这些用于即时修改源代码,也用于动态代码创建,因为在复杂情况下通常更容易将代码作为节点树而不是文本行进行代码。eval
仅允许您评估包含单个表达式的字符串,但您可以eval
一个完整的语句,甚至可以compile> compile
代码> d到bytecode;也就是说,使用Python 2,print
是一个语句,不能直接 led直接:compile
它与'exec'exec'
/code>模式进入代码
对象,您可以eval
it ;eval
功能将返回无
。如果一个人看和
exec
sourcesource source Cpython 3中的代码,这是非常明显的。他们都在使用相同参数的情况下调用
pyeval_evalcode
,唯一的区别是exec
明确返回none
。Python 2和Python 3之间
exec
的语法差异在 是一个内置功能(两者都是Python 3中的内置功能)。众所周知的事实是,python 2中的
exec
的官方语法是exec code [in Globals [,当地人]]
。与python 2-3 ,
exec
cpython 2中的语句也可以与外观 恰好的语法一起使用在Python 3中。原因是Python 0.9.9具有exec(代码,全球,当地人)
内置功能!并用exec
语句在Python 1.0发行之前的某个地方。由于希望不要与python 0.9.9,:如果
代码
是长度2或3的元组,Globals
and code> 未传递到exec
语句中,否则,代码
将被解释为元组的第二个和第三个元素是globals
和当地人分别
。即使在;因此,在记录再次::是的,在CPYTHON 2.7中,它可以用作前向兼容的选项(为什么要使人们完全有一个向后兼容选项感到困惑),
当它实际上是在那里以向后兼容的二十年。
因此,尽管
exec
是Python 1和Python 2中的一个语句,并且在Python 3和Python 0.9.9中的内置功能在可能的每个广泛发布的Python版本中都具有相同的行为;并在Jython 2.5.2,Pypy 2.3.1(Python 2.7.6)和Ironpython 2.6.1(也有密切的无证件行为)。
您在Pythons 1.0-2.7中无法使用其兼容性黑客攻击,是将
exec
的返回值存储到一个变量中: 始终返回
无
),或将引用传递到exec
:哪个模式实际上可能已经使用过的模式,尽管不太可能;
或在列表中使用它:
滥用列表综合(使用循环的
!)。
The short answer, or TL;DR
Basically,
eval
is used to evaluate a single dynamically generated Python expression, andexec
is used to execute dynamically generated Python code only for its side effects.eval
andexec
have these two differences:eval
accepts only a single expression,exec
can take a code block that has Python statements: loops,try: except:
,class
and function/methoddef
initions and so on.An expression in Python is whatever you can have as the value in a variable assignment:
eval
returns the value of the given expression, whereasexec
ignores the return value from its code, and always returnsNone
(in Python 2 it is a statement and cannot be used as an expression, so it really does not return anything).In versions 1.0 - 2.7,
exec
was a statement, because CPython needed to produce a different kind of code object for functions that usedexec
for its side effects inside the function.In Python 3,
exec
is a function; its use has no effect on the compiled bytecode of the function where it is used.Thus basically:
The
compile
in'exec'
mode compiles any number of statements into a bytecode that implicitly always returnsNone
, whereas in'eval'
mode it compiles a single expression into bytecode that returns the value of that expression.In the
'eval'
mode (and thus with theeval
function if a string is passed in), thecompile
raises an exception if the source code contains statements or anything else beyond a single expression:Actually the statement "eval accepts only a single expression" applies only when a string (which contains Python source code) is passed to
eval
. Then it is internally compiled to bytecode usingcompile(source, '<string>', 'eval')
This is where the difference really comes from.If a
code
object (which contains Python bytecode) is passed toexec
oreval
, they behave identically, excepting for the fact thatexec
ignores the return value, still returningNone
always. So it is possible useeval
to execute something that has statements, if you justcompile
d it into bytecode before instead of passing it as a string:works without problems, even though the compiled code contains statements. It still returns
None
, because that is the return value of the code object returned fromcompile
.In the
'eval'
mode (and thus with theeval
function if a string is passed in), thecompile
raises an exception if the source code contains statements or anything else beyond a single expression:The longer answer, a.k.a the gory details
exec
andeval
The
exec
function (which was a statement in Python 2) is used for executing a dynamically created statement or program:The
eval
function does the same for a single expression, and returns the value of the expression:exec
andeval
both accept the program/expression to be run either as astr
,unicode
orbytes
object containing source code, or as acode
object which contains Python bytecode.If a
str
/unicode
/bytes
containing source code was passed toexec
, it behaves equivalently to:and
eval
similarly behaves equivalent to:Since all expressions can be used as statements in Python (these are called the
Expr
nodes in the Python abstract grammar; the opposite is not true), you can always useexec
if you do not need the return value. That is to say, you can use eithereval('my_func(42)')
orexec('my_func(42)')
, the difference being thateval
returns the value returned bymy_func
, andexec
discards it:Of the 2, only
exec
accepts source code that contains statements, likedef
,for
,while
,import
, orclass
, the assignment statement (a.k.aa = 42
), or entire programs:Both
exec
andeval
accept 2 additional positional arguments -globals
andlocals
- which are the global and local variable scopes that the code sees. These default to theglobals()
andlocals()
within the scope that calledexec
oreval
, but any dictionary can be used forglobals
and anymapping
forlocals
(includingdict
of course). These can be used not only to restrict/modify the variables that the code sees, but are often also used for capturing the variables that theexec
uted code creates:(If you display the value of the entire
g
, it would be much longer, becauseexec
andeval
add the built-ins module as__builtins__
to the globals automatically if it is missing).In Python 2, the official syntax for the
exec
statement is actuallyexec code in globals, locals
, as inHowever the alternate syntax
exec(code, globals, locals)
has always been accepted too (see below).compile
The
compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
built-in can be used to speed up repeated invocations of the same code withexec
oreval
by compiling the source into acode
object beforehand. Themode
parameter controls the kind of code fragment thecompile
function accepts and the kind of bytecode it produces. The choices are'eval'
,'exec'
and'single'
:'eval'
mode expects a single expression, and will produce bytecode that when run will return the value of that expression:'exec'
accepts any kinds of python constructs from single expressions to whole modules of code, and executes them as if they were module top-level statements. The code object returnsNone
:'single'
is a limited form of'exec'
which accepts a source code containing a single statement (or multiple statements separated by;
) if the last statement is an expression statement, the resulting bytecode also prints therepr
of the value of that expression to the standard output(!).An
if
-elif
-else
chain, a loop withelse
, andtry
with itsexcept
,else
andfinally
blocks is considered a single statement.A source fragment containing 2 top-level statements is an error for the
'single'
, except in Python 2 there is a bug that sometimes allows multiple toplevel statements in the code; only the first is compiled; the rest are ignored:In Python 2.7.8:
And in Python 3.4.2:
This is very useful for making interactive Python shells. However, the value of the expression is not returned, even if you
eval
the resulting code.Thus greatest distinction of
exec
andeval
actually comes from thecompile
function and its modes.In addition to compiling source code to bytecode,
compile
supports compiling abstract syntax trees (parse trees of Python code) intocode
objects; and source code into abstract syntax trees (theast.parse
is written in Python and just callscompile(source, filename, mode, PyCF_ONLY_AST)
); these are used for example for modifying source code on the fly, and also for dynamic code creation, as it is often easier to handle the code as a tree of nodes instead of lines of text in complex cases.While
eval
only allows you to evaluate a string that contains a single expression, you caneval
a whole statement, or even a whole module that has beencompile
d into bytecode; that is, with Python 2,print
is a statement, and cannot beeval
led directly:compile
it with'exec'
mode into acode
object and you caneval
it; theeval
function will returnNone
.If one looks into
eval
andexec
source code in CPython 3, this is very evident; they both callPyEval_EvalCode
with same arguments, the only difference being thatexec
explicitly returnsNone
.Syntax differences of
exec
between Python 2 and Python 3One of the major differences in Python 2 is that
exec
is a statement andeval
is a built-in function (both are built-in functions in Python 3).It is a well-known fact that the official syntax of
exec
in Python 2 isexec code [in globals[, locals]]
.Unlike majority of the Python 2-to-3 porting guides seem to suggest, the
exec
statement in CPython 2 can be also used with syntax that looks exactly like theexec
function invocation in Python 3. The reason is that Python 0.9.9 had theexec(code, globals, locals)
built-in function! And that built-in function was replaced withexec
statement somewhere before Python 1.0 release.Since it was desirable to not break backwards compatibility with Python 0.9.9, Guido van Rossum added a compatibility hack in 1993: if the
code
was a tuple of length 2 or 3, andglobals
andlocals
were not passed into theexec
statement otherwise, thecode
would be interpreted as if the 2nd and 3rd element of the tuple were theglobals
andlocals
respectively. The compatibility hack was not mentioned even in Python 1.4 documentation (the earliest available version online); and thus was not known to many writers of the porting guides and tools, until it was documented again in November 2012:Yes, in CPython 2.7 that it is handily referred to as being a forward-compatibility option (why confuse people over that there is a backward compatibility option at all),
when it actually had been there for backward-compatibility for two decades.
Thus while
exec
is a statement in Python 1 and Python 2, and a built-in function in Python 3 and Python 0.9.9,has had identical behaviour in possibly every widely released Python version ever; and works in Jython 2.5.2, PyPy 2.3.1 (Python 2.7.6) and IronPython 2.6.1 too (kudos to them following the undocumented behaviour of CPython closely).
What you cannot do in Pythons 1.0 - 2.7 with its compatibility hack, is to store the return value of
exec
into a variable:(which wouldn't be useful in Python 3 either, as
exec
always returnsNone
), or pass a reference toexec
:Which a pattern that someone might actually have used, though unlikely;
Or use it in a list comprehension:
which is abuse of list comprehensions (use a
for
loop instead!).exec
不是一个表达式:python 2.x中的语句,而在python 3.x中的函数。它编译并立即评估字符串中包含的语句或一组语句。示例:eval
是一个内置函数(不是语句),它评估表达式并返回表达式产生的值。示例:compile
是exec
和eval
的较低级别版本。它不会执行或评估您的语句或表达式,而是返回可以执行此操作的代码对象。模式如下:compile(字符串,'','eval')
返回如果您完成eval(contry)(String)的代码对象。 。请注意,您不能在此模式下使用语句;只有(单个)表达式有效。
compile(字符串,','exec')
返回如果您完成exec(String)
,将执行的代码对象。您可以在此处使用任何数量的语句。compile(字符串,'','single')
就像exec
模式,但会完全期望一个表达式/语句,例如compile('a = 1如果1 else 3','myf',mode ='single')
exec
is not an expression: a statement in Python 2.x, and a function in Python 3.x. It compiles and immediately evaluates a statement or set of statement contained in a string. Example:eval
is a built-in function (not a statement), which evaluates an expression and returns the value that expression produces. Example:compile
is a lower level version ofexec
andeval
. It does not execute or evaluate your statements or expressions, but returns a code object that can do it. The modes are as follows:compile(string, '', 'eval')
returns the code object that would have been executed had you doneeval(string)
. Note that you cannot use statements in this mode; only a (single) expression is valid.compile(string, '', 'exec')
returns the code object that would have been executed had you doneexec(string)
. You can use any number of statements here.compile(string, '', 'single')
is like theexec
mode but expects exactly one expression/statement, egcompile('a=1 if 1 else 3', 'myf', mode='single')
Exec用于语句,不返回任何内容。
评估用于表达和返回表达的价值。
表达意味着“某物”,而语句则表示“做某事”。
exec is for statement and does not return anything.
eval is for expression and returns value of expression.
expression means "something" while statement means "do something".