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