Python *.py, *.pyo, *.pyc:哪些可以在嵌入式系统中删除?

12
为了在我目前正在使用的嵌入式系统中腾出有限的文件系统存储空间,我想要消除任何可以合理删除而又不会显着影响功能或性能的文件。Python库中的*.py、*.pyo和*.pyc文件占用了相当大的空间,我想知道在小型嵌入式系统中安装Python 2.6时以下哪种选项最合理:
  1. 保留*.py,消除*.pyc和*.pyo(保持调试能力,性能下降?)
  2. 保留*.py和*.pyc,消除*.pyo(优化真的有所帮助吗?)
  3. 保留*.pyc,消除*.pyo和*.py(这样做可以吗?)
  4. 保留*.py,*.pyc和*.pyo (所有都需要吗?)

据我记忆,.pyc文件是在第一次运行.py文件时自动生成的。 - Powerlord
1
.pyc文件是在第一次导入.py文件时自动生成的。 - Tyler Liu
5个回答

14

http://www.network-theory.co.uk/docs/pytut/CompiledPythonfiles.html

当使用 -O 标志调用 Python 解释器时,会生成优化代码并存储在 '.pyo' 文件中。目前优化器的帮助不大,它只删除 assert 语句。
向 Python 解释器传递两个 -O 标志(-OO)将导致字节码编译器执行优化,这可能在某些罕见情况下导致程序出现故障。目前仅从字节码中删除文档字符串,从而产生更紧凑的 '.pyo' 文件。
我的建议是?
如果您不需要 assert 语句和 __doc__ 字符串,请使用 -OO 仅编译 .pyo 文件。
否则,只使用 .pyc。
编辑
我注意到您只提到了 Python 库。如果您只需要部分功能,则可以删除 Python 库的大部分内容。
我还建议您查看 tinypy,它是大约 64kb 的 Python 大子集。

Tinypy看起来非常有趣,尽管对于我的需求来说可能有点太小了。 - Lance Richardson
1
值得注意的是,pyc文件并不总是能够很好地转移到其他版本的Python。这可能对问题的提出者来说并不是一个问题,但如果他有足够的空间,这将是少了一件要担心的事情。 - Jason Baker
@Jason,Python字节码没有规范。因此,在不同版本之间,pyc和pyo可能会不兼容。 - Unknown
@Unknown:请同时运行Python的优化和非优化版本,并执行“import types”。然后执行(假设在Linux上):“cd /usr/lib/python2.5; ls -l types.py*; grep -F assert types.py”,并解释pyc和pyo文件之间大小的区别。提前感谢您的帮助。 - tzot
1
@ΤΖΩΤΖΙΟΥ。我运行了Python 2.6.2,pyc和pyo文件的大小完全相同。types.py文件中没有断言或非模块文档字符串。 - Unknown

3

第3种方法应该也能够生效,你不需要.pyo或.py文件才能使用编译后的Python代码。


2
以下是我在日常工作中如何最小化主流Python 2.7的磁盘需求的方法:
1)删除标准库中您不需要的软件包。以下是保守的列表:
bsddb/test ctypes/test distutils/tests email/test idlelib lib-tk
lib2to3 pydoc.py tabnanny.py test unittest

请注意,一些Python代码可能会有出人意料的依赖关系;例如,setuptools需要unittest来运行。
2) 预编译所有Python代码,使用-OO来剥离断言和文档字符串。
find -name '*.py' | python -OO -m py_compile -

请注意,默认情况下,Python不会查找`.pyo`文件;您还需要在运行时显式请求进行优化,可以使用选项或环境变量。以以下方式之一运行脚本:
python -OO -m mylib.myscript
PYTHONOPTIMIZE=2 python -m mylib.myscript

3) 删除 .py 源代码文件(除非您需要将它们作为脚本运行)和 .pyc 未优化文件。

find '(' -name '*.py' -or -name '*.pyc' ')' -and -not -executable -execdir rm '{}' ';'

4) 压缩Python库文件。Python可以从zip文件中加载模块。zip文件中的路径必须与包层次结构匹配;因此,在压缩之前,您应该将site-packages.egg目录合并到主库目录中。(或者您可以将多个zip文件添加到Python路径中。)

在Linux上,默认路径已包括/usr/lib/python27.zip,因此只需将zip文件放置在那里即可。

os.pyo保留为普通文件(非压缩文件),因为Python会将其视为健全性检查。如果将其移动到zip文件中,每次调用Python时都会收到警告(尽管一切仍将正常工作)。或者你可以只留一个空的os.py文件,并将真正的文件放在zip文件中。

最后注意事项:

  • 通过这种方式,Python占用7MB的磁盘空间。还有很多可以做的来减小大小,但是7MB对于我的目的来说足够小了。 :)
  • Python字节码在不同版本之间不兼容,但是当编译和控制Python版本的是你自己时,谁在乎呢?
  • .pyo文件在zip文件中应该在所有情况下都是性能优势,除非磁盘速度极快且处理器/内存极慢。无论哪种方式,Python都是从内存中执行,而不是从磁盘格式中执行,因此它仅会影响加载时的性能。尽管剥离文档字符串可以节省相当多的内存。
  • 请注意,.pyo文件不包含assert语句。
  • .pyo文件保留函数名称和行号,因此调试性并没有降低:您仍然可以获得良好的跟踪信息,只需手动查找源代码中的行号,这也是必须要做的。
  • 如果要在运行时“hack”文件,请将其放在当前工作目录中。它优先于库zip文件。

2
我建议只保留.py文件。启动时间的差异并不是很大,而且保留源代码是一个优点,因为它可以在不同的Python版本下运行而不会出现任何问题。
从Python 2.6开始,将sys.dont_write_bytecode设置为True将完全禁止编译.pyc和.pyo文件,所以如果您有2.6可用,您可能想使用该选项。

1
归根结底,你只需要三个选项中的一个,但最好选择.pys和.pyos或.pycs。
以下是我对每个选项的看法:
  1. 如果你把.pys文件放在一个zip文件中,就不会生成pycs或pyos文件。需要指出的是,性能差异只存在于启动时间上,即使在我的经验中也不太明显(但你的情况可能有所不同)。此外,还要注意一种方法可以防止解释器输出.pycs文件,正如Algorias所指出的那样。
  2. 我认为这是一个理想的选择(或者是.pys和.pyos),因为你可以获得最佳的性能、调试性和可靠性混合。虽然你不一定需要源文件和编译文件。
  3. 如果你真的缺乏空间并且需要性能,这个方法可以使用。但我建议你尽可能保留.pys文件。编译后的二进制文件(.pycs或.pyos)并不总是适用于不同版本的Python。
  4. 除非你计划有时运行优化模式,有时运行非优化模式,否则你不太可能需要这三个文件。
从空间角度来看,根据我的(非常主观的)经验,如果你把.py文件放在zip文件中,它们比.pycs和.pyos压缩得更好。如果你计划压缩这些文件,.pyos不会在纯空间方面获得太多优势,因为文档字符串往往可以很好地压缩,而断言占用的空间并不是很大。

1
他正在使用嵌入式系统,因此如果您选择将.py文件放在zip文件中,他将不得不承担在内存中解压缩的额外负担(而他可能甚至没有足够的内存)。 - Unknown
你可能是对的。我主要是想指出每种方法的优缺点,而不推荐“最佳”方法,因为我不知道OP需要什么具体内容。 - Jason Baker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接