android 在什么情况下会主动gc_Python 什么情况下会生成 pyc 文件?

a38d97ac31481605525db1c305dc21a0.png

作者:折木奉太郎(经授权转载)来源:https://www.zhihu.com/question/30296617/answer/112564303

作为 Python 爱好者,需要了解 .py 脚本的基本运行机制特性

在很多工作上,Python 的运行流程基本上取决于用户,因此源码不需要编译成二进制代码(否则无法实现大部分贴近用户的特性),而直接从源码运行程序。当我们运行 Python 文件程序的时候,Python 解释器将源码转换为字节码,然后再由解释器来执行这些字节码。

因此总的来说,它具有以下三条特性:

  1. 源码距离底层更远(根据官方文档的解释。不说,你们也感觉得到)(。・`ω´・)

  2. 运行时都需要生成字节码,交由虚拟机执行。(你们问我虚拟机在哪儿?!你们也不看看各自都是用什么软件执行的!没错,就是解释器,别和我说是 IDLE 啊。虚拟机具体实现了由 switch-case 语句构成的框架函数 PyEval_EvalFrameEx,刚刚说的字节码就是这货执行的)

  3. 每次执行脚本,虚拟机总要多出加载和链接的流程。(所以呢,相比于编译型语言就有点慢了。这与“有丝分裂间期”一样,准备东西也要花时间啊!)

那么,有人要问了:“不是说,运行时总要生成字节码么!那,字节码都去哪儿了?” 咳咳,别急!容我先说说,虚拟机它是怎么执行脚本的(咕噜咕噜喝杯水...):
  1. 完成模块的加载和链接;

  2. 将源代码翻译为 PyCodeObject 对象(这货就是字节码),并将其写入内存当中(方便 CPU 读取,起到加速程序运行的作用);

  3. 从上述内存空间中读取指令并执行;

  4. 程序结束后,根据命令行调用情况(即运行程序的方式)决定是否将 PyCodeObject 写回硬盘当中(也就是直接复制到 .pyc 或 .pyo 文件中);

  5. 之后若再次执行该脚本,则先检查本地是否有上述字节码文件。有则执行,否则重复上述步骤。

你看!在我们点击(或输入命令)运行脚本,并悠闲地喝咖啡时,“人家”虚拟机做了这么多的事情。不过,你有没有发现 .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 文件(默认),对应的参数解释如下

  1. file,表示需要生成 .pyc 或 .pyo 文件的源脚本名(字符串);

  2. cfile,表示需要生成 .pyc 或 .pyo 文件的目标脚本名。呃...好像没有区别(>﹏<) ,也就是源脚本-----[巴拉拉赐予你力量!编译!]( * ̄▽ ̄)o ─═≡※:☆----->目标脚本。当然,它默认是以 .pyc 为扩展名的路径名的字符串(呼...好长)。此外,当且仅当所使用的解释器允许编译成 .pyo 文件,才能以“.pyo”结尾。这也就是我上面为什么会在函数功能解释上加上“(默认)”这两个字的原因。

  3. dfile,表示编译出错时,将报错信息中的名字“file”替换为“dfile”

  4. doraise设置是否忽略异常。若为 True,则抛出 PyCompileError 异常;否则直接将错误信息写入 sys.stderr(什么!不知道 sys.stderr?!温馨提示:sys.stderr 是 Python 自带的标准错误输出)

(╯' - ')╯︵ ┻━┻ (掀桌子) ┬─┬ ノ( ' - 'ノ) (摆好摆好) (╯°Д°)╯︵ ┻━┻(再TA喵掀一次)

另外,生成 .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 文件又是什么鬼(>﹏<)?!(问题真多,精分ing...) 别在意,那只是 Python 的动态链接库。如果要深究,还得扯上 C++ 的知识(长篇大论的,会被喷的啊)。

再啰嗦一句:生成字节码的方法多了去了,不止以上这几种。比如,你们不妨试试将上面命令行调用中的“py_compile”改成“compileall”,而代码行中的“py_compile.compile”改成“compileall.compile_file”或“compileall.compile_dir”,又或者直接使用带有编译功能的 IDE 生成字节码。

再再啰嗦一句:知道 Python 运行机制,并不是我们一般人所必须的(吃瓜群众:“滚!我刚好不容易看完了,你才说?!”)。但是,了解其加速程序运行以及优化代码的设计思想,对于我们在日后构造缓存系统、如何减少不必要的运行时间,以及同步更新工作内容等问题上起到很大的借鉴作用。

若想要了解更多的内容,可以去翻翻官方文档和其它博客:

https://docs.python.org/3.5/using/cmdline.html?highlight=#command-line-and-environmenthttps://docs.python.org/3.5/library/py_compile.html?highlight=.pyc#module-py_compilehttps://docs.python.org/3.5/c-api/code.html?highlight=pycodeobject#code-objectshttp://nedbatchelder.com/blog/200804/the_structure_of_pyc_files.htmlhttp://www.tuicool.com/articles/Q7Rj6rrhttp://developer.51cto.com/art/201002/184914.html

好文章,我在看❤️

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/336387.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【IP协议头分析】

Version 版本号 IHL IP头长度 Type of Service Total Length 总长度 Identification 拆包的唯一标识 Flags 1位保留 , 2位 允许拆包 3位 不允许拆包 Fragment offset 在原包偏移量 Time to Live 时间或路由跳数 Protocol IP中是什么协议类型 Header Check…

乡村野生草药_官方野生蝇群流口水分数

乡村野生草药官方是什么? 标题太小,但有用的贡献。 Wildfly Swarm允许我们创建相当小的自包含应用程序,包括我们从Wildfly Application Server中需要的应用程序。 在这篇文章中,我们将研究与Wildfly Swarm合作使用的Drools分数 。…

obs多推流地址_(无人直播)教程利用OBS推流抖音直播电脑屏幕或PC游戏

目前的火爆程度相信大家都有目共睹,也為部分活躍用戶提供直播功能,開通直播的方法有:①粉絲達到10000粉絲,官方會自動邀請妳開通直播權限。②加入和官方合作的工會,無需粉絲,也可以開通直播權限。開通直播功…

倒数日电脑版_应用日报|iOS 或更名为 iPhoneOS,倒数日 Mac 版上线限时免费

今日推荐倒数日 Days Matter for Desktop免费,macOS 86 MB倒数日 Days Matter 是 iOS 端非常经典的应用,今天它的 Mac 版本上线,限时免费 7 天。它延续了 iOS 端的风格语言,同样能帮你记录生活中重要的日子:例如恋人…

【TPC协议头解析】

Source Port 源端口 Destination Port 目的端口 Sequence Number 数据报编号 (seq)(按字节序)保证有序 Acknowledgment Number (ACK) 报文应答, 保证可靠性 Data offset 跳到data数据部分 Reserved 保留部分 URG 紧急数据标识 ACK 确认消息…

iphone新旧手机数据传输已取消_如何取消iPhone手机App自动扣费?三种方法让你不再被“偷”...

一直以来苹果手机App这个自动续费真是让大家不胜其烦,钱虽然不多可总是平白无故这里十块,那里二十块的被扣也是不小的浪费,日常生活中为了追追剧、听听音乐、玩玩游戏难免会开通一些App会员而选择自动续费的话每月会费是有不错优惠的&#xf…

【TCP三次握手与四次挥手最强解析】

TCP连接拥塞控制四种方法总结(详细简单,稳的一批) TCP三次握手 作用:确认seqnumber;确定窗口大小以及最大报文大小 TCP四次挥手 WAIT_TIME状态到CLOSED需要2MSL时间(最长单位MSL为2min,一般30s&#xff0…

oracle基础授权,Oracle基础学习3--Oracle创建用户并授权

Oracle服务器端的操作一般如下:1)安装Oracle服务器软件2) 创建数据库(安装时自动创建)3) 配置监听(安装时自动配置)4) 启动Oracle实例5) 创建用户表空间6) 创建新用户并授权下面就开始讲创建用户表空间、创建新用户并授权两项&#x…

mybatis缓存二级缓存_MyBatis缓存与Apache Ignite的陷阱

mybatis缓存二级缓存一周前,MyBatis和Apache ignite 宣布支持apache ignite作为MyBatis缓存(L2缓存)。 从技术上讲,MyBatis支持两个级别的缓存: 本地缓存,默认情况下始终启用 L2缓存,可选 随…

企业是否应该实现对客户需求的快速响应_CRM系统给企业带来的创新有哪些?如何让销售爱用CRM系统?...

对于现代企业来说,CRM已然成为了一个成熟的项目,是能够给客户带来不菲的价值的。如果应用好,是能够取得提高客户满意度与企业经济效益的双赢成绩的。一、目前,CRM能够给企业带来的业务创新有哪些?1.统一数据CRM系统能将…

junit注释_通过此注释改善您的JUnit体验

junit注释JUnit可能是所有Java项目中90%的一部分。 令人兴奋的是,我们很快将拥有支持Java 8的JUnit 5 。 我们最近在博客上发表了一项改进 。 回到JUnit 4领域,有一个小技巧,我只能建议您进行所有单元测试。 只需在此处添加这个小…

lagom的微服务框架_微服务有麻烦吗? Lagom在这里为您提供帮助。 试试吧!

lagom的微服务框架蛋糕支持。 我们很自豪地宣布,新的Apache许可的微服务框架Lagom可在GitHub上使用 ! 当其他框架专注于打包和实例启动时,Lagom重新定义了Java开发人员构建基于微服务的应用程序的方式。 服务是异步的。 服务内通信由您管理。…

python离线安装包_Python2.7如何离线安装包

1 Python版本是2.7已经在CentOS7系统自带,没有pip,没有互联网环境,需要先安装 backports.ssl_match_hostname-3.4.0.2.tar.gz,直接再CentOS7系统运行以下命令: 解压tar文件 tar -xvf backports.ssl_match_hostname-3.4…

【音视频安卓开发 (三)】OpenGL ES 直接绘制YUV

EGL OpenGL与窗口对应的的适配层,针对安卓平台的适配器。 surface 交互到窗口显示

上网登录窗不弹出_配置 Windows XP 正常上网(TLS HTTPS),连接到 NAS

Windows XP 是经典的、高效的、可靠的、性能良好的操作系统,然而其大部分版本都已在 2014 年停止支持。其较为流行的版本 SP2 与 SP3 由于各种原因,目前均不能直接正常访问安装了 SSL 证书的网站,或映射某些服务器提供的共享文件夹。本文将提…

oracle数据库集群日志,Oracle集群数据库中恢复归档日志

恢复归档日志:select * from v$log_history t where t.THREAD#恢复归档日志:select * from v$log_history t where t.THREAD#1order by t.FIRST_TIME desc实例1:恢复一个归档日志:run{allocate channel dev_0 type sbt_tapeparms …

jcmd 命令_jcmd:一个可以全部统治的JDK命令行工具

jcmd 命令我在过去的几篇文章中都引用了方便的JDK工具jcmd ,但是像我以前对jps所做的那样,只专注于它的实用性 。 jcmd工具是随Oracle Java 7引入的,通过使用它来识别Java进程的ID (与jps相似),获取堆转储 …

【流媒体FLV封装协议】

FLV封装格式介绍及解析 FLV封装格式 FLV(Flash Video)是Adobe公司推出的一种流媒体格式,由于其封装后的音视频文件体积小、封装简单等特点,非常适合于互联网上使用。目前主流的视频网站基本都支持FLV。采用FLV格式封装的文件后缀为.flv。 FLV封装格式…