动态编译
标准编程语言
对于 C 语言,代码一般要先编译,再执行。
.c -> .exe
解释器语言
shell 脚本
.sh -> interpreter
Byte Code 编译
Python, Java 等语言先将代码编译为 byte code(不是机器码),然后再处理:
.py -> .pyc -> interpreter
eval 函数
eval(statement, glob, local)
使用 eval
函数动态执行代码,返回执行的值:
In [1]:
- a = 1
- eval("a+1")
Out[1]:
- 2
可以接收明明空间参数:
In [2]:
- local = dict(a=2)
- glob = {}
- eval("a+1", glob, local)
Out[2]:
- 3
这里 local
中的 a
先被找到。
exec 函数
exec(statement, glob, local)
使用 exec
可以添加修改原有的变量。
In [3]:
- a = 1
- exec("b = a+1")
- print b
- 2
In [4]:
- local = dict(a=2)
- glob = {}
- exec("b = a+1", glob, local)
- print local
- {'a': 2, 'b': 3}
执行之后,b
在 local
命名空间中。
警告
动态执行的时候要注意,不要执行不信任的用户输入,因为它们拥有 Python
的全部权限。
compile 函数生成 byte code
compile(str, filename, mode)
In [5]:
- a = 1
- c = compile("a+2", "", 'eval')
- eval(c)
Out[5]:
- 3
In [6]:
- a = 1
- c = compile("b=a+2", "", 'exec')
- exec(c)
- b
Out[6]:
- 3
abstract syntax trees
In [7]:
- import ast
In [8]:
- tree = ast.parse("a+2", "", "eval")
- ast.dump(tree)
Out[8]:
- "Expression(body=BinOp(left=Name(id='a', ctx=Load()), op=Add(), right=Num(n=2)))"
改变常数的值:
In [9]:
- tree.body.right.n = 3
- ast.dump(tree)
Out[9]:
- "Expression(body=BinOp(left=Name(id='a', ctx=Load()), op=Add(), right=Num(n=3)))"
In [10]:
- a = 1
- c = compile(tree, '', 'eval')
- eval(c)
Out[10]:
- 4
安全的使用方法 literal_eval
,只支持基本值的操作:
In [11]:
- ast.literal_eval("[10.0, 2, True, 'foo']")
Out[11]:
- [10.0, 2, True, 'foo']