网站建设宣传ppt模板,公司网站的好处,wordpress更改地址后404.3,长沙网站建设推广作为Python爱好者#xff0c;需要了解.py脚本的基本运行机制及特性#xff1a;
在很多工作上Python的运行流程基本上取决于用户#xff0c;因此源码不需要编译成二进制代码#xff08;否则无法实现大部分贴近用户的特性#xff09;#xff0c;而直接从源码运行程序。当我…作为Python爱好者需要了解.py脚本的基本运行机制及特性
在很多工作上Python的运行流程基本上取决于用户因此源码不需要编译成二进制代码否则无法实现大部分贴近用户的特性而直接从源码运行程序。当我们运行python文件程序的时候Python解释器将源码转换为字节码然后再由解释器来执行这些字节码。
因此总的来说它具有以下三条特性
源码距离底层更远根据官方文档的解释。不说你们也感觉得到。
运行时都需要生成字节码交由虚拟机执行。你们问我虚拟机在哪儿你们也不看看各自都是用什么软件执行的没错就是解释器别和我说是IDLE啊。虚拟机具体实现了由switch-case语句构成的框架函数PyEval_EvalFrameEx刚刚说的字节码就是这货执行的。
每次执行脚本虚拟机总要多出加载和链接的流程。所以呢相比于编译型语言就有点慢了。这与“有丝分裂间期”一样准备东西也要花时间啊
那么有人要问了“不是说运行时总要生成字节码么那字节码都去哪儿了”
咳咳别急容我先说说虚拟机它是怎么执行脚本的
完成模块的加载和链接
将源代码翻译为PyCodeObject对象这货就是字节码并将其写入内存当中方便CPU读取起到加速程序运行的作用
从上述内存空间中读取指令并执行
程序结束后根据命令行调用情况即运行程序的方式决定是否将PyCodeObject写回硬盘当中也就是直接复制到.pyc或.pyo文件中
之后若再次执行该脚本则先检查本地是否有上述字节码文件。有则执行否则重复上述步骤。
你看在我们点击或输入命令运行脚本并悠闲地喝咖啡时“人家”虚拟机做了这么多的事情。不过你有没有发现.pyc或.pyo文件是否生成是取决于我们如何运行程序的虽然我们不知道要怎么做。
同样有人会吐槽“哼为什么不直接生成这些文件这样来得不是‘更快、更高、更强’”
其实虚拟机也是讲究效率的。毕竟对于比较大的项目要将PyCodeObject写回硬盘也是不可避免地要花些时间的而且它又不知道你是不是也就只执行一次之后就对刚刚跑完的脚本“弃之不顾”了呢。不过它其实也有贴心的一面。
比如若你在命令行直接输入“python path/to/projectDir”假设projectDir目录含有“main.py”文件以及其他将要调用的模块那么程序运行结束后便自动为当前目录下所有的脚本生成字节码文件并保存于本地新文件夹pycache当中。这也有可能是IDE写小项目时自动生成.pyc文件的原因不过问题描述略微暧昧。详情参见上面知乎问题板块
或者是在命令行输入“python path/to/projectDir/main.py”则生成除main.py外脚本的字节码文件。
不过总的来说上述这两种行为都大大缩短了项目运行前的准备时间毕竟分工明确的程序规模应该不会太小复用率也不会太低。除非吃饱了撑着搞出这么多事情
模块在每次导入前总会检查其字节码文件的修改时间是否与自身的一致。若是则直接从该字节码文件读取内容否则源模块重新导入并在最后生成同名文件覆盖当前已有的字节码从而完成内容的更新详见import.py。
这样就避免了修改源代码后与本地字节码文件产生冲突当然设计者也不会这么傻。。
若想优化生成字节码应注意这两点
.pyc文件是由.py文件经过编译后生成的字节码文件其加载速度相对于之前的.py文件有所提高而且还可以实现源码隐藏以及一定程度上的反编译。比如Python3.3编译生成的.pyc文件Python3.4就别想着去运行啦
.pyo文件也是优化注意这两个字便于后续的理解编译后的程序相比于.pyc文件更小也可以提高加载速度。但对于嵌入式系统它可将所需模块编译成.pyo文件以减少容量。
但总的来说作用上是几乎与原来的.py脚本没有区别的也就是“然并卵 ”当然并非毫无作用。比如我个人觉得用处最大的地方就是防止别人偷看我的代码毕竟.py源文件是直接以源码的形式呈现给大家的。
在所有的Python选项中
-O表示优化生成.pyo字节码这里又有“优化”两个字得注意啦
-OO表示进一步移除-O选项生成的字节码文件中的文档字符串这是在作用效果上解释的而不是说从-O选项得到的文件去除
-m表示导入并运行指定的模块
对此我们可以使用如下格式运行.py文件来生成.pyc文件以下调用均假设/path/to目录含有.py脚本
python -m py_compile /path/to/需要生成.pyc的脚本.py #若批量处理.py文件
#则替换为/path/to/{需要生成.pyc的脚本1,脚本2,...}.py
#或者/path/to/
其效果等效于如下代码
import py_compile
py_compile.compile(r/path/to/需要生成.pyc的脚本.py) #同样也可以是包含.py文件的目录路径
#此处尽可能使用raw字符串从而避免转义的麻烦。比如这里不加“r”的话你就得对斜杠进行转义
py_compile是Python的自带模块这里面就两个函数。其下的py_compile.compile(file[, cfile[, dfile[, doraise]]])可将.py文件编译生成.pyc文件默认对应的参数解释如下
file表示需要生成.pyc或.pyo文件的源脚本名字符串
cfile表示需要生成.pyc或.pyo文件的目标脚本名。呃...好像没有区别﹏ 也就是源脚本-----[巴拉拉赐予你力量编译] *▽o ─═≡※:☆-----目标脚本。当然它默认是以.pyc为扩展名的路径名的字符串呼...好长。此外当且仅当所使用的解释器允许编译成.pyo文件才能以“.pyo”结尾。这也就是我上面为什么会在函数功能解释上加上“默认”这两个字的原因。
dfile表示编译出错时将报错信息中的名字“file”替换为“dfile”。
doraise设置是否忽略异常。若为True则抛出PyCompileError异常否则直接将错误信息写入sys.stderr什么不知道sys.stderr温馨提示sys.stderr是Python自带的标准错误输出
另外生成.pyo文件的格式调用如下
python -O -m py_compile /path/to/需要生成.pyo的脚本.py
那么有人要问了为什么不是像生成.pyc文件那样采用“python -O /path/to/需要生成.pyo的脚本.py”形式的调用
“忘记”说明这一点了很多博客以及书籍都像我上面那样解释“-O”选项的作用但详细来解释的话是-O选项将.pyc文件优化注意我一直强调的“优化”二字这里就用到啦为.pyo文件而不是将.py文件优化编译为.pyo文件。其直接的结果是优化编译后的文件略微小于.pyc文件也就是“减肥”了。现在大家知道.pyo文件为什么小的原因了吧
注意
以上无论是生成.pyc还是.pyo文件都将在当前脚本的目录下生成一个含有字节码的文件夹pycache。
可能还有人会问.pyd文件又是什么鬼
别在意那只是Python的动态链接库。如果要深究还得扯上C的知识。
再啰嗦一句生成字节码的方法多了去了不止以上这几种。比如你们不妨试试将上面命令行调用中的“py_compile”改成“compileall”而代码行中的“py_compile.compile”改成“compileall.compile_file”或“compileall.compile_dir”又或者直接使用带有编译功能的IDE生成字节码。
再再啰嗦一句知道Python运行机制并不是我们一般人所必须的吃瓜群众“滚我刚好不容易看完了你才说”。但是了解其加速程序运行以及优化代码的设计思想对于我们在日后构造缓存系统、如何减少不必要的运行时间以及同步更新工作内容等问题上起到很大的借鉴作用。
若想要了解更多的内容可以去翻翻官方文档和其他博客
我将优质的技术文章和经验总结都汇集在了我的公众号【Python圈子】里。
在学习Python的道路上肯定会遇见困难别慌我这里有一套学习资料包含40本电子书600个教学视频涉及Python基础、爬虫、框架、数据分析、机器学习等不怕你学不会还有学习交流群一起学习进步~