什么是“bad magic number”错误?

372

Python中的"Bad magic number" ImportError是什么,我该如何修复它?

网络上能找到的唯一信息表明,这是由于将.py文件编译为.pyc文件,然后尝试在错误的Python版本中使用它所导致的。然而,在我的情况下,该文件有时可以正常导入,有时却不行,我不确定原因。

Python提供的回溯信息并不特别有用(这就是我在这里询问的原因......),但如果有帮助的话,以下是相关信息:

Traceback (most recent call last):
  File "run.py", line 7, in <module>
    from Normalization import Normalizer

你能提供出现问题的代码吗? - Evan Fosmark
你使用的是哪个版本的Python? - paxdiablo
3
好的,我认为当我移动.py文件时留下了一个旧的.pyc文件,导致我可能正在导入旧版本的文件,因此我可以导入新版本但无法导入旧版本。 - Noah
1
我删除了旧的.pyc文件,所以现在没有它了,但我的问题出在导入路径上——如果我没有移动.py文件,Python会使用它来重新创建.pyc文件,这样对吗? - Noah
我在使用在Centos 6.5机器上编译的Python 2.7的pyc文件时遇到了这个错误(该机器自带Python 2.6)。 - Broken_Window
显示剩余5条评论
15个回答

492

魔数来自于类UNIX系统,文件的前几个字节保存了标记,指示文件类型。

当Python创建pyc文件时,会将类似的标记放入其中。

然后,Python解释器在加载文件时确保该数字正确。

任何损坏此魔数的操作都会导致问题。这包括编辑pyc文件或尝试从比您的解释器版本(通常是更新版本)更高的Python版本运行pyc文件。

如果它们是您的pyc文件(或者您有它们的py文件),只需删除它们,让解释器重新编译py文件即可。在类UNIX系统上,这可能只需要执行以下简单命令:

rm *.pyc

或者:

find . -name '*.pyc' -delete

如果它们不是你的,而且原始的py文件没有提供,那么你就必须要么获取py文件进行重新编译,要么使用一个可以运行具有特定魔术值的pyc文件的解释器。

可能会导致间歇性问题的一件事是,引起问题的pyc文件只能在某些条件下被导入。它很难只是有时候导入。当导入失败时,应该检查实际的完整堆栈跟踪。

另外,我所有的2.5.1(r251:54863)pyc文件的第一个单词都是621312.6.1(r261:67517)62161。所有魔术数字的列表可以在Python/import.c中找到,为了完整起见,在此重复(当前答案发布时的最新版本,现在已经更改):

1.5:   20121
1.5.1: 20121
1.5.2: 20121
1.6:   50428
2.0:   50823
2.0.1: 50823
2.1:   60202
2.1.1: 60202
2.1.2: 60202
2.2:   60717
2.3a0: 62011
2.3a0: 62021
2.3a0: 62011
2.4a0: 62041
2.4a3: 62051
2.4b1: 62061
2.5a0: 62071
2.5a0: 62081
2.5a0: 62091
2.5a0: 62092
2.5b3: 62101
2.5b3: 62111
2.5c1: 62121
2.5c2: 62131
2.6a0: 62151
2.6a1: 62161
2.7a0: 62171

7
谢谢,虽然这并没有直接帮助我解决我的问题,但知道答案还是很好的! - Noah
1
我该如何检查是哪个pyc文件引起了问题?我已经删除了所有的pyc文件,但仍然出现这个错误。 - sunprophit
1
也许你现在需要运行 'rm pycache/*pyc',因为pyc文件现在在那个文件夹里。 - Arpad Horvath -- Слава Україні
1
谢谢!我遇到了同样的问题:ERROR:tornado.general:无法加载 'es' 的翻译文件:[Errno 0] Bad magic number: '/app/locale/es/LC_MESSAGES/django.mo'。实际上,问题出在 *.mo 文件没有正确编译。 - ericson.cepeda
1
更详细的列表在这里:https://github.com/google/pytype/blob/master/pytype/pyc/magic.py - Davy
显示剩余5条评论

70

删除所有的 .pyc 文件将修复“Bad Magic Number”错误。

find . -name "*.pyc" -delete

8
最好使用 find . -name "*.pyc" -delete,因为如果你展开所有文件名并将其传递给 rm,可能会遇到空格问题(以及可能的过长命令行问题)。请注意,此翻译仅作参考,确保根据上下文和特定情况进行适当调整。 - Andrew Aylett
36
我认为这是一个相当危险的脚本。如果有一个只包含 .pyc 文件以保持闭源的软件包被交付,会怎样?哎呀,您刚刚删除了应用程序。 - Dan Mantyla
4
最好先运行 find . -name "*.pyc" -print,然后手动删除有问题的文件,或者在确认不会出现问题后再运行上述命令。请注意,不要做出后悔的事情。 - michael
13
闭源软件包无论如何都应该被删除。 - cat

34

使用Python2加载由Python3生成的*.pyc文件也会导致此错误。


7
这可能是一条评论,而不是答案。 - Kroltan
3
@Kroltan,这个回答非常好,比被采纳的那个更好。简洁明了,重点突出。 - Antony Hatchkins
1
@AntonyHatchkins 在我看来,这可能是对任何建议删除 .pyc 的答案的评论。即使这是一种可能的原因,但它没有不同的解决方案,因此这是多余的。如有不同意见,请随意反驳,这只是我的观点。 - Kroltan
1
@Kroltan 这里的“如何修复”部分非常明显。而真正有趣的是原因,至少对我来说是这样。我曾经尝试过使用不同的Python 2.x版本进行编程,但从未遇到过.pyc版本之间的不兼容性问题。而这个解决方案则表明了Python3与Python2之间的问题 - 而这一信息在被接受的答案中并没有提到。此外,我喜欢简短的答案(如果可能的话) :) - Antony Hatchkins
1
@Antony,我理解你的想法。就我个人而言,我更喜欢在解决问题的同时进行教育(教人捕鱼),但我能理解你的观点。谢谢。 - paxdiablo
显示剩余4条评论

6
将pyc文件带到Windows机器上。使用任何十六进制编辑器打开此pyc文件。我使用的是免费软件“HexEdit”。现在读取前两个字节的十六进制值。在我的情况下,它们是03 f3。
打开计算器并将其显示模式转换为程序员(XP中为科学)以查看十六进制和十进制转换。从单选按钮中选择“Hex”。先输入第二个字节的值,然后再输入第一个字节,即f303。现在单击“Dec”(十进制)单选按钮。显示的值对应于Python的魔法数字,也就是版本号。
因此,考虑到之前回复中提供的表格:
1.5 => 20121 => 4E99,所以文件的第一个字节应为99,第二个字节应为4e 1.6 => 50428 => C4FC,所以文件的第一个字节应为fc,第二个字节应为c4

4

这可能是由于目录中缺少__init__.py文件引起的。例如,如果您在Django中创建一个新目录以将单元测试分离为多个文件并将它们放置在一个目录中,则还必须在新创建的测试目录中的所有其他文件旁边创建__init__.py文件。否则,会出现如下错误:

Traceback (most recent call last):
  File "C:\Users\USERNAME\AppData\Local\Programs\Python\Python35\Lib\unittest\loader.py",line 153, in loadTestsFromName
    module = __import__(module_name)
ImportError: bad magic number in 'APPNAME.tests': b'\x03\xf3\r\n'

3
“Bad magic number”错误也会发生在您手动将文件命名为扩展名为.pyc的情况下。

3
在我的情况下,不是.pyc文件,而是旧的二进制.mo翻译文件,因为我重命名了自己的模块,所以在该模块文件夹内,我需要运行以下命令:
find . -name \*.po -execdir sh -c 'msgfmt "$0" -o `basename $0 .po`.mo' '{}' \;

(请务必备份并尝试修复 .pyc 文件)


1
我遇到了一个奇怪的问题,使用一个非常旧的(1.5.2)实现时出现了Bad Magic Number错误。我生成了一个.pyo文件,触发了这个错误。奇怪的是,通过改变模块的名称来解决了这个问题。有问题的名称是sms.py。如果我从该模块生成sms.pyo,就会出现Bad Magic Number错误。当我将名称更改为smst.py时,错误消失了。我反复检查,看看sms.py是否与任何其他同名模块产生干扰,但我没有找到任何名称冲突。尽管这个问题的根源对我来说仍然是个谜,但我建议尝试更改模块名称。

0

这比上面更加高效。

find {directory-of-.pyc-files} -name "*.pyc" -print0 | xargs -0 rm -rf

其中{directory-of-.pyc-files}是包含编译后Python文件的目录。


1
那是在你手头有py文件的情况下,如果没有,你就需要降级Python安装。 - Leon Fedotov
1
这对于某些边缘情况仍然不安全。另外,当我们谈论文件时,为什么要进行递归删除? - user256434
1
为什么要使用两个进程?即使find没有delete,您仍然可以运行“find /dir -name“*.pyc”-exec rm '{}' ';'” - mikemaccana
1
“find” 命令如果默认使用 -print 终止符直接由 xargs rm 使用,则无法安全地处理带有空格的文件名。Python 不会导入非标识符命名的文件,但脚本仍可能导致此问题,并且它们不会被删除。通常更安全的方法是在 find 命令上使用额外的 -print0(末尾为零)(作为“|”管道符号之前的最后一个参数),然后在将 find 管道传递到 xargs 时使用 -0 选项(即连字符 + 零)以理解 -print0 输出,再执行 rm 命令。 - Breezer

0

如果你的操作系统是Windows,那么这也可能是由于错误的python27.dll文件引起的。为了解决这个问题,只需重新安装(或提取)与dll版本完全对应的Python即可。我曾经有过类似的经历。


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