python预编译是什么意思

Python012

python预编译是什么意思,第1张

预编译又称为预处理,是做些代码文本的替换工作。处理#开头的指令,比如拷贝#include包含的文件代码,#define宏定义的替换,条件编译等,就是为编译做的预备工作的阶段主要处理#开始的预编译指令。

编译(compilation , compile)

1、利用编译程序从源语言编写的源程序产生目标程序的过程。

2、用编译程序产生目标程序的动作。 编译就是把高级语言变成计算机可以识别的2进制语言,计算机只认识1和0,编译程序把人们熟悉的语言换成2进制的。

更多Python知识请关注Python视频教程栏目。

文件是在导入编译。 这不是一个安全的事情。 这仅仅是如果你将其导入蟒蛇保存输出。 看到这个帖子由Fredrik Lundh开发上Effbot。

>>>import main 

# main.pyc is created 

当运行一个脚本巨蟒将不使用* .pyc文件的文件。 如果你有你想要你的脚本一些其他的原因,预编译可以使用compileall模块

python -m compileall . 

compileall用法

python -m compileall --help 

option --help not recognized 

usage: python compileall.py [-l] [-f] [-q] [-d destdir] [-x regexp] [directory ...] 

-l: don't recurse down 

-f: force rebuild even if timestamps are up-to-date 

-q: quiet operation 

-d destdir: purported directory name for error messages 

if no directory arguments, -l sys.path is assumed 

-x regexp: skip files matching the regular expression regexp 

the regexp is searched for in the full path of the file 

回答以下问题编辑

如果响应是潜在的磁盘权限的目录main.py ,为什么Python的编译模块?

模块和脚本将被视为相同。 进口是什么触发要保存的输出。

如果原因是好处将是最小的,可以考虑的情况时,该脚本将被用于大量的时间(诸如在一个CGI应用程序)。

使用compileall不解决这个问题。 由蟒蛇执行的脚本将不使用*.pyc ,除非明确要求。 这有负面影响,深受格伦·梅纳德在他的回答说。

CGI应用程序的给出的例子确实应该使用像FastCGI的技术来解决。 如果你想消除编译脚本的开销,可能要消除启动蟒蛇太大,何况数据库连接开销的开销。

光引导脚本可以用来甚至python -c "import script" ,但这些都值得商榷的风格。

格伦·梅纳德提供一些灵感来纠正和改进这个答案。

似乎没有人想这样说,但我敢肯定的答案很简单:有这种行为没有坚实的理由。

所有到目前为止所提出的理由基本上是不正确的:

没有什么特别的主文件。 它作为一个模块加载,并显示了sys.modules像任何其他模块。 运行主脚本无非就是用的模块名称导入更__main__ 。

有与没有保存.pyc文件由于只读目录中的文件没有问题蟒蛇简单地忽略它,并在移动。

缓存脚本的好处是相同缓存任何模块的:不浪费时间每次它的运行时间重新编译脚本。 该文档明确地承认这一点(“因此,脚本的启动时间可能会减少......”)。

另一个问题需要注意:如果您运行python foo.py和foo.pyc存在,它不会被使用 。 你必须明确地说, python foo.pyc 。 这是一个非常糟糕的主意:它意味着当它是不同步的Python不会自动重新编译的.pyc文件的文件(由于.py文件变化),因此对.py文件的更改将不会使用,直到您手动重新编译。 它也将与抛出一个RuntimeError彻底失败如果升级的Python和.pyc文件的文件格式不再兼容,这经常发生。 通常情况下,这是所有透明地处理。

你不应该需要一个脚本移动到一个虚拟的模块,并成立了引导脚本欺骗的Python到其高速缓存。 这是一个hackish的解决方法。

唯一可能(而且非常缺乏说服力)我之所以能凑合是避免从一堆pyc文件被杂乱的主目录。 (这不是真正的理由如果这是一个实际的问题,则pyc文件应保存为点文件)。这当然没有理由不甚至有一个选项来做到这一点。

蟒绝对应该能够缓存主模块。

以来:

当它从.pyc文件或.pyo文件时,它是从一个.py文件阅读不是阅读程序不会跑得更快这是关于.pyc文件或.pyo文件的速度的唯一事情就是与它们加载速度。

这是不必要的,以产生用于主脚本pyc文件的文件。 只有那些可能会被加载多次图书馆应编制。

编辑 :

这似乎你没明白我的意思。 首先,认识到编制的整体思路.pyc文件也作出了同样的文件在第二次执行速度更快。 然而,考虑是否做的Python编译脚本正在运行。 解释器将字节码写入到一个.pyc的文件在第一次运行,这需要时间。 因此,它甚至会运行有点慢。 你可能会认为它会更快之后运行。 好吧,这只是一个选择。 此外,作为this说:

明确优于隐式。

如果想通过使用加速.pyc的文件,应该手动编译并运行.pyc明确文件。

要回答你的问题,参考6.1.3。 “编译”Python文件在Python正式文件。

当脚本由命令行上给出它的名字运行,脚本的字节码不会被写入一个.pyc文件或.pyo文件。 因此,脚本的启动时间可通过移动它的大部分代码的一个模块,并具有导入这个模块一小启动脚本减少。 另外,也可以命名.pyc文件或直接.pyo文件的命令行上。

教育学

让我又爱又恨类似这样的问题上如此,因为有感情,意见的复杂混合物,和受过教育的猜测事情,人们开始变得snippy,不知何故每个人都失去了赛道的实际情况,最终失去了轨道原题的共。

这么多的技术问题都至少有一个明确的答案,但这些“为什么”的问题往往没有只是一个单一的,确定的答案(例如,可以通过执行或引用权威人士的答案来验证答案)。 在我看来,有两个可能的方式来明确回答计算机科学“为什么”的问题:

通过指向一个实现所关注的项目的源代码。 这就解释了“为什么”从技术角度来看:什么前提条件是必要的,以唤起这种行为?

通过指向人类可读的文物(注释,提交信息,邮件列表等)由参与作出该决定的开发人员编写的。 这就是“为什么”,我假设OP是感兴趣的真正意义:为什么Python的开发人员使这种看似随意的决定?

第二种回答是更加难以证实,因为它需要获得在谁写的代码开发者的心,特别是如果没有容易找到,公开文件中的特定行为的决定。

迄今为止,这个讨论有7回答是只专注于阅读的Python的开发者的意图,但只有一个在整批引用 。 (它引用了不回答OP的问题了Python手册的部分。)

这是我在与沿引用既回答了“为什么”的问题两侧的尝试。

源代码

什么是触发.pyc文件编制的前提条件? 让我们来看看源代码。 (烦人,在GitHub上Python没有发布任何标记,所以我就告诉你,我在寻找715a6e )。

有在希望的代码import.c:989在load_source_module()函数。 我在这里切出一些位为简洁起见。

static PyObject * 

load_source_module(char *name, char *pathname, FILE *fp) 

// snip...

if (/* Can we read a .pyc file? */) { 

/* Then use the .pyc file. */ 

else { 

co = parse_source_module(pathname, fp) 

if (co == NULL) 

return NULL 

if (Py_VerboseFlag) 

PySys_WriteStderr("import %s # from %s\n", 

name, pathname) 

if (cpathname) { 

PyObject *ro = PySys_GetObject("dont_write_bytecode") 

if (ro == NULL || !PyObject_IsTrue(ro)) 

write_compiled_module(co, cpathname, &st) 

m = PyImport_ExecCodeModuleEx(name, (PyObject *)co, pathname) 

Py_DECREF(co)

return m 

pathname是路径模块和cpathname是相同的路径,但是用pyc文件扩展名。 唯一的直接逻辑是布尔sys.dont_write_bytecode 。 逻辑的其余部分就是错误处理。 因此,我们所寻求的答案不在这里,但我们至少可以看到,调用此的任何代码将导致在大多数默认配置的.pyc文件的文件。 该parse_source_module()函数没有真正意义要执行的流程,但我会在这里显示,因为我会回来稍后。

static PyCodeObject * 

parse_source_module(const char *pathname, FILE *fp) 

PyCodeObject *co = NULL 

mod_ty mod 

PyCompilerFlags flags 

PyArena *arena = PyArena_New() 

if (arena == NULL) 

return NULL

flags.cf_flags = 0

mod = PyParser_ASTFromFile(fp, pathname, Py_file_input, 0, 0, &flags, 

NULL, arena) 

if (mod) { 

co = PyAST_Compile(mod, pathname, NULL, arena) 

PyArena_Free(arena) 

return co 

这里的显着的方面是,函数解析和编译的文件,并返回一个指针的字节代码(如果成功)。

现在,我们仍处于一个死胡同,让我们处理这个从一个新的角度。 如何Python中加载它的参数,并执行它? 在pythonrun.c有用于从文件加载代码并执行它的几个功能。 PyRun_AnyFileExFlags()可以处理交互式和非交互式的文件描述符。 对于交互式的文件描述符,它委托给PyRun_InteractiveLoopFlags()这是REPL)和非交互式的文件描述符,它委托给PyRun_SimpleFileExFlags() PyRun_SimpleFileExFlags()检查文件名 中结束.pyc 。 如果这样做的话,就调用run_pyc_file()直接加载编译字节码从一个文件描述符然后运行它。

在更常见的情况下(即.py文件作为参数), PyRun_SimpleFileExFlags()调用PyRun_FileExFlags()这是我们开始找到了答案。

PyObject * 

PyRun_FileExFlags(FILE *fp, const char *filename, int start, PyObject *globals, 

PyObject *locals, int closeit, PyCompilerFlags *flags) 

PyObject *ret 

mod_ty mod 

PyArena *arena = PyArena_New() 

if (arena == NULL) 

return NULL

mod = PyParser_ASTFromFile(fp, filename, start, 0, 0, 

flags, NULL, arena) 

if (closeit) 

fclose(fp) 

if (mod == NULL) { 

PyArena_Free(arena) 

return NULL 

ret = run_mod(mod, filename, globals, locals, flags, arena) 

PyArena_Free(arena) 

return ret 

}

static PyObject * 

run_mod(mod_ty mod, const char *filename, PyObject *globals, PyObject *locals, 

PyCompilerFlags *flags, PyArena *arena) 

PyCodeObject *co 

PyObject *v 

co = PyAST_Compile(mod, filename, flags, arena) 

if (co == NULL) 

return NULL 

v = PyEval_EvalCode(co, globals, locals) 

Py_DECREF(co) 

return v 

这里的突出的一点是,这两个函数基本上执行相同的目的,进口商的load_source_module()和parse_source_module() 它调用解析器创建从Python源代码的AST,然后调用编译器创建字节码。

那么,这些代码块多余的还是他们的目的不同? 不同的是,一个块加载从文件的模块,而其他块使用的是模块作为参数。 该模块的说法是-在这种情况下-在__main__模块,它使用的是低级别的C函数早些时候在初始化过程中创建的。 该__main__模块不通过最正常的模块导入代码路径,因为它是如此独特,并且作为一个副作用,它不通过产生代码去.pyc的文件。

总结:为什么原因__main__ 。模块未编译.pyc文件是它是不是“进口”是的,它出现在sys.modules中,但它通过不是真正的模块导入采取了非常不同的代码路径到达那里。

开发者意图

好了,我们现在可以看到的行为更多的是与Python的设计比在源代码中任何明确表达的理由,但是这并没有回答这是否是一种有意的决定,或只是一个副作用的问题这不打扰任何人足以成为值得改变。 一个开源的好处是,一旦我们发现我们感兴趣的源代码,我们可以使用VCS帮助追溯,导致目前实施的决定。

其中代码的关键行这里( m = PyImport_AddModule("__main__") )的历史可以追溯到1990年,并在自己BDFL,圭多写的。 它已被修改,在干预的岁月,但修改是肤浅的。 当它第一次写,一个脚本参数主模块初始化是这样的:

int 

run_script(fp, filename) 

FILE *fp 

char *filename 

object *m, *d, *v 

m = add_module("`__main__`") 

if (m == NULL) 

return -1 

d = getmoduledict(m) 

v = run_file(fp, filename, file_input, d, d) 

flushline() 

if (v == NULL) { 

print_error() 

return -1 

DECREF(v) 

return 0 

这之前存在.pyc的文件甚至被引入到Python的! 难怪当时的设计没有考虑汇编成账户脚本参数。 提交信息神秘地说:

“编译”版本

这是几十的一个承诺,在3天的时间......看来,圭多是深入到一些黑客/重构,这是一回到是稳定的第一个版本。 这种承诺甚至五年左右早于Python的开发邮件列表的创建!

保存编译的字节码引入以后6个月,于1991年。

这仍然早于列表服务,所以我们有一个什么样圭多想没有真正的想法。 看来,他只是认为,进口商为挂接到缓存字节码的目的,最好的地方。 他是否考虑做同样为理念__main__不清:要么没有想到他,不然他认为这是更多的麻烦比它的价值。

我无法找到要缓存为主要模块的字节码相关的bugs.python.org任何错误,也可以找到关于它的邮件列表上的任何消息,因此,显然没有人认为这是值得的麻烦尝试添加它。

总结:为什么所有模块编译的缘故.pyc除了__main__是,它是历史的怪癖如何设计和实现。 __main__被作品烤成代码前.pyc的文件,即使存在。 如果你想知道的多的是,你需要电子邮件圭多和要求。

格伦·梅纳德的回答说:

似乎没有人想这样说,但我敢肯定的答案很简单:有这种行为没有坚实的理由。

我同意100%。 有间接证据来支持这一理论,没有人在这个线程别人提供的证据来支持任何其他理论的一个切丝。 我upvoted格伦的回答。

因为剧本正在运行可能会在某处是不恰当的生成pyc文件,如/usr/bin 。

Python(发音:英[ˈpaɪθən],美[ˈpaɪθɑ:n]),是一种易学且功能强大的编程语言。

这种语言的名字(Python意为“蟒蛇”)来自于BBC节目“Monty Python的飞行马戏团”,而与爬行动物没有关系。在文档中用Monty Python来开玩笑不只是可以的,还是可以推荐的!

Python具有高级有效的数据结构和简单有效的面向对象编程。

Python优雅的语法和动态类型,加上它的解释性,使它成为很多编程平台开放开源和快速开发应用的理想语言。

Python 解释器及丰富的标准库以源码或机器码的形式提供,可以到 Python 官网 www.python.org 免费获取。在下载时要注意你所使用的操作系统类型。在这个官方网站上还提供了许多免费的第三方 Python 模块、程序和工具以及附加文档的发布页面或链接。

Python很容易使用,但它是一种真正的编程语言,提供了很多数据结构,也支持大型程序,远超shell脚本或批处理文件的功能。Python还提供比C语言更多的错误检查,而且作为一种“超高级语言”,它有高级的内置数据类型,比如灵活的数组和字典。正因为这些更加通用的数据类型,Python能够应付更多的问题,超过Awk甚至Perl,而且很多东西在Python中至少和那些语言同样简单。

Python 允许你划分程序模块,在其他的 Python 程序中重用。它内置了很多的标准模块,你可以在此基础上开发程序——也可以作为例子,开始学习 Python 编程。例如,文件输入输出,系统调用,套接字,甚至图形界面接口工作包比如 Tk 。

Python是一种解释型语言,在程序开发阶段可以为你节省大量时间,因为不需要编译和链接。解释器可以交互式使用,这样就可以方便地尝试语言特性,写一些一次性的程序,或者在自下向上的程序开发中测试功能。

Python也是一个顺手的桌面计算器。

Python程序的书写是紧凑而易读的。Python代码通常比同样功能的C,C++,Java代码要短很多,原因列举如下:

(1)高级数据类型允许在一个表达式中表示复杂的操作;

(2)代码块的划分是按照缩进而不是成对的花括号;

(3)不需要预先定义变量或参数。

Python是“可扩展的”:如果你知道怎么写C语言程序,就能很容易地给解释器添加新的内置函数或模块,不论是让关键的程序以最高速度运行,还是把Python程序链接到只提供预编译程序的库(比如硬件相关的图形库)。一旦你真正链接上了,就能在Python解释器中扩展或者控制C语言编写的应用了。

Python本身提供了非常完善的基础代码库,覆盖了网络、文件、GUI、数据库、文本等大量内容。所以,使用Python开发程序,你不必从0开始做,使用基础代码库或第三方库就可以轻松帮助你完成大量的工作。

在实际中,许多大型网站就是用Python开发的,例如YouTube、Instagram,还有国内的豆瓣。很多大公司,包括Google、Yahoo等,甚至NASA(美国航空航天局)都在大量地使用Python。因此,你学习或使用Python并不孤单。

但是,Python并不是完美的,也并非万能的。它的第一个缺点就是运行速度慢,由于Python是解释型语言,与其它编译型语言比起来要慢得多,不过当前的计算机硬件和网络设备的性能改善很多,而且很多情况下,你不需要那么快的速度去做工作,Python的慢性子是可以忍受的。

它的第二个缺点就是代码是可见的,你编写的Python程序共享给其他人时,其他人是可以看到源代码的,这一方面是由于Python的宗旨是开源共享,另外一方面是它是解释型的,拿过来,用你的Python解释器直接解释运行就可以了,没必要封装编译成机器代码。

(注:本文整理了官方文档与网络其它文档中的一些内容)

本号将在今后逐步发布Python方面的文章,希望你能收藏关注本号,有空来看看,留下你的足迹,给本站前行的动力。

微信搜索 “优雅的代码” 关注本站的公众号,以获取最新内容。

个人成长离不开各位的关注,你的关注就是我继续前行的动力。