if you want to use exec and you plan on executing that code more than
once, make sure you compile it into bytecode first and then execute
that bytecode only and only in a new dictionary as namespace.
特别值得注意的是:
Now how much faster is executing bytecode over creating bytecode and
executing that?:
$ python -mtimeit -s 'code = "a = 2; b = 3; c = a * b"' 'exec code'
10000 loops, best of 3: 22.7 usec per loop
$ python -mtimeit -s 'code = compile("a = 2; b = 3; c = a * b",
"", "exec")' 'exec code' 1000000 loops, best of 3: 0.765 usec
per loop
32 times as fast for a very short code example. It becomes a lot worse
the more code you have. Why is that the case? Because parsing Python
code and converting that into Bytecode is an expensive operation
compared to evaluating the bytecode. That of course also affects
execfile which totally does not use bytecode caches, how should it.
It's not gonna magically check if there is a .pyc file if you are
passing the path to a foo.py file.
回答动态自然的问题,不,不是真的。生成的代码对象仍然被解释;相同的字节码仍在运行。在
我见过的compile()(和代码生成)最有用/最令人印象深刻的用法是在Jinja2中。实际上,它从模板生成Python代码,然后使用compile以“本机”(native)(==解释器)的速度运行(如果有意义的话)。在
https://github.com/mitsuhiko/jinja2/blob/master/jinja2/environment.py#L506
相比之下,比如说,django.template,它在“用户空间”中执行变量查找等(同样,可以说,隐喻有点奇怪)。在
https://github.com/django/django/blob/master/django/template/base.py#L752
从这里:What's the difference between eval, exec, and compile in Python?:
compile
是exec
和eval
的低级版本。它不执行或计算您的语句或表达式,但返回可以执行此操作的代码对象。模式如下:compile(string, '', 'eval')
返回完成eval(string)
时将执行的代码对象。注意,不能在此模式下使用语句;只有(单个)表达式有效。在compile(string, '', 'exec')
返回完成exec(string)
时将执行的代码对象。这里可以使用任意数量的语句。在compile(string, '', 'single')
类似于exec
模式,但它将忽略除第一个语句之外的所有内容。注意,if
/else
语句及其结果被视为单个语句。在更新:
何时编译Python?
通常编译Python是为了利用性能。编译后的代码不需要编译,所以启动时间要快得多,但它的运行速度并不比编译的快。在
最值得注意的是,如果您想手工将代码转换为字节码,您可以使用
compile
。这就引出了另一个重要但相关的问题为什么要这样做?在如本magnificent article中所述:
特别值得注意的是:
相关问题 更多 >
编程相关推荐