Python 2.5 .pyc文件是否与Python 2.6 .pyc文件兼容?

时间:2010-02-14 23:48:52

标签: python

前段时间我不得不将一些服务器从Python 2.4升级到Python 2.5。我发现当Python 2.5试图运行它们时,在Python 2.4下创建的.pyc文件会崩溃。

当我从2.5升级到2.6时会再次发生吗?

编辑:这里有更多细节

我有一个包含python代码的文件服务器。 Ubuntu和Windows服务器都可以访问它来运行python代码。当他们运行代码时,他们会在文件服务器上生成.pyc文件。

我发现当我将其中一台服务器机器从Python 2.4升级到2.5时,我遇到了.pyc文件的问题。我现在不确定是否是运行2.5的机器试图运行2.4字节码或者它是否是2.4机器试图运行2.5字节码,但是如果我删除了字节码一直顺利,直到下一个字节码发生冲突。

我将所有机器升级到2.5,问题就消失了。

5 个答案:

答案 0 :(得分:13)

通常,.pyc文件特定于一个Python版本(尽管可以跨不同的机器架构移植,只要它们运行相同的版本);这些文件在其标题中包含有关相关Python版本的信息 - 因此,如果您将相应的.py文件保留在.pyc文件旁边,则.pyc每次都会重建.pyc不同的Python版本用于导入这些模块。 “试图运行”错误版本.py文件是我从未听说过的。涉及哪些架构?是.py文件应该是什么?

编辑:因为OP澄清了当他在相同的.py文件上运行Python 2.4 Python 2.5程序时出现崩溃(来自两个)不同的服务器,共享一个网络驱动器),崩溃的解释变得容易。 .pyc文件一直在重新编译 - 当2.4最近运行它们时由2.4 Python编译,反之亦然 - 因此.pyc文件疯狂地被重写每时每刻。网络驱动器上的正确文件锁定(特别是但不仅限于不同的操作系统)是非常难以实现的。所以必须发生以下情况(可以切换角色):2.4服务器刚刚确定.py文件对它很好并开始阅读它;在它完成阅读之前,2.5服务器(之前已经确定需要重新编译的模块)写了它;所以2.4服务器最终得到了一个内存缓冲区,它具有(比方说)2.4版本的前4K字节和2.5版本的下一个4K字节。当它使用那个错误的缓冲区时,毫不奇怪...... 崩溃 !!!

如果您发现自己不断尝试从两个或多个不同版本的Python运行一组.pyc文件(即使在同一台服务器上,而不会增加网络驱动器的复杂性),这可能是一个真正的问题)。 “适当”的解决方案就像virtualenv。我们在工作中采用的(简单但很脏的)hack(很多年前,但它仍然在生产中......!)是修补每个版本的Python来为其编译的字节码文件生成和使用不同的扩展:{ {1}}(或.pyo)用于Python 1.5.2(这是我们开始为新版本开发此版本时最稳定的“系统”版本),.pyc-2.0 for 2.0,{ {1}}表示2.2,依此类推(或等同于.pyc-2.2)。我听说这很快就会消失(感谢托马斯! - ),但很多年来,它确实让我们在这个棘手的问题上半得体。

一个更简单的解决方案是保持单个版本的Python,如果这对您的系统可行;如果你的系统有任何复杂性使得单个Python版本不可行(就像我们做的那样),那么这些天我会衷心地推荐.pyo-X.Y,我已经提到了。


在Python 3.2中采用PEP 3147,不同Python版本的pyc文件会根据文件名自动区分。这可以解决大多数问题,不同的Python版本会覆盖彼此的pyc文件。

答案 1 :(得分:5)

如果您有源代码,那么它将为您重新编译它。所以一般来说你没事。

但是,如果具有不同版本Python的用户从中央安装目录运行,这可能对您不利。

如果你只有pyc文件也可能不好。我刚给你做了快速测试。我创建了两个.pyc文件。一分为2.5分,一分为2.6分。 2.5不会在2.6中运行,2.6不会在2.5中运行。两者都抛出“ImportError:Bad magic number in ..”错误,这是有道理的,因为幻数已经从2.5变为2.6。

如果您想提前确定,可以按如下方式获取Python的幻数:

$ python -V
Python 2.6.2
# python
>>> import imp
>>> imp.get_magic().encode('hex')
'd1f20d0a'

要获取pyc文件的幻数,您可以执行以下操作:

>>> f = open('test25.pyc')
>>> magic = f.read(4)
>>> magic.encode('hex')
'b3f20d0a'
>>> f = open('test26.pyc')
>>> magic = f.read(4)
>>> magic.encode('hex')
'd1f20d0a'

答案 2 :(得分:2)

创建文件的Python版本存储在.pyc文件中。 通常这意味着.pyc被正确的Python版本替换为

这可能不会发生的一些原因 - 权限
- .py文件不可用

在权限问题的情况下,Python将只使用.py并忽略.pyc(以性能为代价)

我觉得在次要版本之间没问题,例如Python2.6.2 .pyc应该适用于Python2.6.4

以下是/ usr / share / file / magic

的摘录
# python:  file(1) magic for python
0   string      """ a python script text executable
0   belong      0x994e0d0a  python 1.5/1.6 byte-compiled
0   belong      0x87c60d0a  python 2.0 byte-compiled
0   belong      0x2aeb0d0a  python 2.1 byte-compiled
0   belong      0x2ded0d0a  python 2.2 byte-compiled
0   belong      0x3bf20d0a  python 2.3 byte-compiled
0   belong      0x6df20d0a  python 2.4 byte-compiled
0   belong      0xb3f20d0a  python 2.5 byte-compiled
0   belong      0xd1f20d0a  python 2.6 byte-compiled

因此,您可以看到正确的Python版本由.pyc文件的前4个字节指示

答案 3 :(得分:1)

请参阅http://www.python.org/dev/peps/pep-3149/以获取针对此的建议修补程序(希望在Python 3.2中)

答案 4 :(得分:0)

您肯定需要重新编译字节码文件才能使用它们。字节码幻数已经在每个主要版本的Python(*)上发生了变化。

但是,使用非版本匹配的字节码文件不应该使Python崩溃。它通常只会忽略任何没有正确版本号的字节码,因此不应该出现错误,它会在重新编译时第一次变慢(如果运行脚本的用户不是每次都会变慢)没有更新字节码的写权限。

(*:通常在开发阶段,加上早期版本,它有时也会改变次要版本。请参阅import.c以获取幻数及其相应Python版本的完整列表。)