Python内置“compile”的主要用途是什么?

2024-03-29 02:06:32 发布

您现在位置:Python中文网/ 问答频道 /正文

在查看Python built-in函数列表时,我很难理解方法^{}的有用性。所有我能找到的例子都指向一个简单的“hello world”。它所做的事情是有意义的,但在使用它时却没有意义。在

这是Python用来生成.pyc文件的方法吗?在

这可以用来消除Python的一些动态特性,以提高某些代码块的性能吗?(非常清楚地知道C中的模块是预编译模块的方法。)


Tags: 模块文件方法函数inhello列表world
2条回答

回答动态自然的问题,不,不是真的。生成的代码对象仍然被解释;相同的字节码仍在运行。在

我见过的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?

compileexeceval的低级版本。它不执行或计算您的语句或表达式,但返回可以执行此操作的代码对象。模式如下:

  1. compile(string, '', 'eval')返回完成eval(string)时将执行的代码对象。注意,不能在此模式下使用语句;只有(单个)表达式有效。在
  2. compile(string, '', 'exec')返回完成exec(string)时将执行的代码对象。这里可以使用任意数量的语句。在
  3. compile(string, '', 'single')类似于exec模式,但它将忽略除第一个语句之外的所有内容。注意,if/else语句及其结果被视为单个语句。在

更新:

何时编译Python?

通常编译Python是为了利用性能。编译后的代码不需要编译,所以启动时间要快得多,但它的运行速度并不比编译的快。在

最值得注意的是,如果您想手工将代码转换为字节码,您可以使用compile。这就引出了另一个重要但相关的问题为什么要这样做?在

如本magnificent article中所述:

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.

相关问题 更多 >