作者: Jim Wang 公众号: 巴博萨船长

虽然Python简单并且容易部署,平时开发时,除了常见的py和pyc文件后缀以外,其实python还有一些别的文件扩展名。我们这篇文章就归纳总结一下所有的与python相关的文件扩展名filename extension(又称后缀名)与各种文件扩展名的文件是如何产生,每种文件文件扩展名的作用。

与Python有关扩展名

  • .py - 最基本的文件扩展名
  • .py3 - (极其少见) Python3 源码文件扩展名. Python3 的正式源码后缀名也为”.py” 不是 “.py3”, 但py3也曾在一些地方出现。
  • .pyc - 源码编译过的文件的扩展名 (字节码)。
  • .pyo - 与pyc一样也是编译过的文件的文件扩展名。优化编译后的程序(相比于.pyc文件更小),也可以提高加载速度。对于嵌入式系统,它可将所需模块编译成.pyo文件以减少容量需求。
  • .pyw - 和py相似,是源码扩展名,跟py扩展名的区别是在windows下双击pyw扩展名的源码会调用pythonw.exe执行源码,这种执行方式不会有命令行窗口,用于GUI程序发布时不需要看到控制台信息的情况。linux环境中,pyw和pyc没有区别。
  • .pyx - Cython 源码,与C/C++源码.c/.cpp相似,不像 Python 语言可直接解释使用的 .py 文件,.pyx 文件必须先被编译成 .c 文件,再编译成 .pyd (Windows 平台) 或 .so (Linux 平台) 文件,才可作为模块 import 导入使用。
  • .pyd - pyd并非从python程序生成,而是其他语言写成的可以被python调用的扩展,例如C++写的(Windows平台dll,Linux 平台.so)动态连接库供python调用。
  • .pxd - Cython 源码头文件,与C/C++源码.h相似。pxd 文件中有 Cython 模块要包含的 Cython 声明 (或代码段)。.pxd 文件可共享外部 C 语言声明,也能包含 C 编译器内联函数。.pxd 文件还可为 .pyx 文件模块提供 Cython 接口,以便其它 Cython 模块可使用比 Python 更高效的协议与之进行通信。可用 cimport 关键字将 .pxd 文件导入 .pyx 模块文件中。
  • .pxi - MyPy存根。
  • .pyi - 存根文件,替代.pxi。 (参考:PEP 484),如果想在Python编译时实现类型检查,需要用MyPy。 MyPy包含生成.pyi文件的stubgen.py工具。
  • .pyz - Python脚本归档**(参考:PEP 441)**(这是一个包含标准Python脚本头之后的二进制形式的压缩Python脚本(ZIP)的脚本)
  • .pywz - 用于MS-Windows的Python脚本归档(**参考:PEP 441)**,如上.pyz。
  • .py[cod] - 版本管理工具Git的忽略文件.gitignore中的通配符,表示需要忽略的文件可能是.pyc,.pyo或.pyd。
  • .rpy- 包含应用程序或框架特定功能的RPython脚本或Python脚本
  • .pyde - 处理使用的Python脚本
  • .pyp - Py4D Python插件
  • .pyt - Python 工具箱 (.pyt) 只是一个基于 ASCII 的文件,该文件定义了工具箱和一个或多个工具。(参**考:ArcGIS)**

扩展名相互关系

大部分情况下,我们创建的Python脚本都是以.py为文件扩展名。py文件可以通过python命令或者自己写的py脚本进行编译成pyc。使用命令的方法如下,在cmd输入以下内容。

1
2
3
python -m py_compile /path/to/mycode.py #若批量处理.py文件
#则替换为/path/to/{需要生成.pyc的文件1,文件2,...}.py
#或者/path/to/

也可以在python文件中实现上述过程。

1
2
3
4
5
6
7
#对于文件                                                      
import py_compile
py_compile.compile(r'/path/to/mycode.py') #.py文件
#此处尽可能使用raw字符串,从而避免转义的麻烦。
#比如,这里不加“r”的话,你就得对斜杠进行转义 #对于文件夹
import compileall
compileall.compile_dir("mylib", force=1)

当然如果希望生成.pyo,则可以使用如下命令:

1
python -O -m py_compile /path/to/mycode.py #文件或者目录

-O选项,将.pyc文件优化为.pyo文件,而不是将.py 文件优化编译为.pyo文件。优化编译后的文件略微小于.pyc文件, 减少储存的需求。

编译过后的字节码文件.pyc可以反编译成.py文件。反编译软件叫Easy Python Decompiler,可以从网上自己下载,该工具很容易上手,可以反编译一个文件也可以是文件夹。

虽然编译过后的二进制的字节码可以被反编译。但是如果你不希望自己的代码被别人直接读取,那么可以将字节码.pyc文件打包并公布。虽然与Python的开源精神不相符,但是也算是折中的安全机制。但是值得注意的是:.pyc文件与Python的版本有依赖。即,如果你用Python X编译的pyc文件不能再Python Y中使用,这里的X,Y为代指某些版本,无特定意义。如果强制加载将会引发ImportError异常,异常关键字为Bad magic Number。

下列是部分版本的Magic Number,全部列表请(参考:Magic_Nr):

1
2
3
4
5
6
2.5b3: 62111
2.5c1: 62121
2.5c2: 62131
2.6a0: 62151
2.6a1: 62161
2.7a0: 62171

小结

Python 3.x 的编译过程是与Python2.x 有区别的,Python 3.x 编译的pyc的时候,会在当前目录里生成一个名为pycache的文件夹,为什么会存在该文件夹?Python解释器会将 .py 脚本文件进行编译,并将编译结果保存到pycache目录中。下次再执行时,如果解释器发现某个 .py 脚本没有修改过,就会跳过编译这一步,直接运行以前生成的保存在 pycache文件夹里的 *.pyc 文件。这样就可以大大缩短项目运行前的准备时间;如果你只需执行一个小工程,没关系 忽略这个文件夹就行。而此时你打包pyc的时候就会发现该文件不能正常地被加载,会提示一些错误,常见的错误是解释器和文件路径不匹配。

为了避免上述的问题,我们可以在编译的时候输入特定的参数,如下:

1
python3 -m compileall -b test3

选项-b,指定编译pyc文件的输出到它们的原始位置。(即与Python2中相同)。

这篇文章我们不过多讨论如何生成Pyd文件,和使用这样的文件,该部分内容,我将在以后的关于在python中使用C/C++代码的文章中详细解释。上述内容是自己在Python应用中遇到过的问题,总有不足之处,望见谅并指正。

参考目录:

PEP:441:https://www.python.org/dev/peps/pep-0484/#stub-files

PEP:441:https://www.python.org/dev/peps/pep-0441/

ERSI ArcGIS:http://desktop.arcgis.com/zh-cn/arcmap/10.3/analyze/creating-tools/a-quick-tour-of-python-toolboxes.htm

Magic_Nr: https://github.com/google/pytype/blob/master/pytype/pyc/ magic.py


版权声明:
文章首发于 Jim Wang's blog , 转载文章请务必以超链接形式标明文章出处,作者信息及本版权声明。