Lỗi số ma thuật xấu là gì?


320

"Số ma thuật xấu" ImportError trong python là gì và làm cách nào để khắc phục nó?

Điều duy nhất tôi có thể tìm thấy trực tuyến cho thấy điều này là do biên dịch tệp .py -> .pyc và sau đó cố gắng sử dụng nó với phiên bản sai của python. Tuy nhiên, trong trường hợp của tôi, tệp dường như nhập tốt một số lần nhưng không phải là tệp khác và tôi không chắc tại sao.

Thông tin mà python cung cấp trong truy nguyên không đặc biệt hữu ích (đó là lý do tại sao tôi hỏi ở đây ...), nhưng đây là trong trường hợp nó giúp:

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

Bạn có thể cung cấp mã trong đó vấn đề đang xảy ra?
Evan Fosmark

Và phiên bản nào của python bạn đang sử dụng?
paxdiablo

Và là Chuẩn hóa một trong các tệp của bạn hoặc của bên thứ ba?
paxdiablo

3
Hrm, okay, tôi nghĩ rằng tôi đã phải nhập một tệp .pyc cũ đã bị bỏ lại từ lâu khi tôi di chuyển tệp .py, và vì vậy tôi có thể nhập phiên bản mới nhưng không phải là phiên bản cũ.

1
Tôi đã cắt tệp .pyc cũ, vì vậy tôi không có nó, nhưng vấn đề của tôi là với các đường dẫn nhập - Tôi nghĩ python sẽ sử dụng tệp .py để tạo lại tệp .pyc nếu tôi không di chuyển nó (đúng không?)

Câu trả lời:


400

Số ma thuật đến từ các hệ thống kiểu UNIX trong đó một vài byte đầu tiên của tệp chứa một điểm đánh dấu cho biết loại tệp.

Python đặt một điểm đánh dấu tương tự vào các pyctệp của nó khi nó tạo chúng.

Sau đó, trình thông dịch python đảm bảo số này là chính xác khi tải nó.

Bất cứ điều gì làm hỏng số ma thuật này sẽ gây ra vấn đề của bạn. Điều này bao gồm chỉnh sửa pyctệp hoặc cố gắng chạy một pycphiên bản khác của python (thường là sau này) so với trình thông dịch của bạn.

Nếu chúng là tệp của bạn pyc , chỉ cần xóa chúng và để trình thông dịch biên dịch lại pycác tệp. Trên các hệ thống loại UNIX, đó có thể là một cái gì đó đơn giản như:

rm *.pyc

hoặc là:

find . -name '*.pyc' -delete

Nếu chúng không phải của bạn, bạn sẽ phải lấy các pytệp để biên dịch lại hoặc trình thông dịch có thể chạy các pyctệp có giá trị ma thuật cụ thể đó.

Một điều có thể gây ra bản chất không liên tục. Điều pycđó gây ra vấn đề chỉ có thể được nhập khẩu trong một số điều kiện nhất định. Đôi khi rất khó có thể nhập khẩu. Bạn nên kiểm tra theo dõi ngăn xếp đầy đủ thực tế khi nhập thất bại?

Là một sang một bên, từ đầu tiên của tất cả của tôi 2.5.1(r251:54863) pycfile là 62131, 2.6.1(r261:67517)62161. Danh sách tất cả các số ma thuật có thể được tìm thấy Python/import.c, được sao chép ở đây cho đầy đủ (hiện tại vào thời điểm câu trả lời được đăng, nó có thể đã thay đổi kể từ đó):

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

2
Cảm ơn - điều này không trực tiếp giúp tôi tìm ra vấn đề của mình, nhưng thật tuyệt khi biết câu trả lời nào!

Làm cách nào để kiểm tra tệp pyc nào gây ra sự cố, tôi đã xóa tất cả các tệp pyc nhưng vẫn gặp lỗi này.
sunprophit

Có lẽ bạn cần 'rm __pycache __ / * pyc' ngay bây giờ, vì các tệp pyc hiện có trong thư mục đó.
Arpad Horvath

1
Cảm ơn! Điều đó đã xảy ra với tôi với: ERROR: tornado.general: Không thể tải bản dịch cho 'es': [Errno 0] Số ma thuật xấu: '/app/locale/es/LC_MESSAGES/django.mo'. Trên thực tế, đó là * .mo không được biên dịch chính xác.
ericson.cepeda

1
Danh sách mở rộng hơn tại đây: github.com/google/pytype/blob/master/pytype/pyc/magic.py
Davy

60

Xóa tất cả các tệp .pyc sẽ sửa lỗi "Bad Magic Number".

find . -name "*.pyc" -delete

8
Có lẽ tốt hơn để sử dụng find . -name "*.pyc" -delete, vì bạn sẽ gặp vấn đề với khoảng trắng (và có thể với dòng lệnh quá dài) nếu bạn mở rộng tất cả tên tệp để chuyển đến rm.
Andrew Aylett

25
IMO đó là một kịch bản khá nguy hiểm. Điều gì xảy ra nếu một gói được phân phối chỉ với các tệp .pyc để giữ cho nó đóng nguồn? Rất tiếc, bạn vừa xóa ứng dụng.
Dan Mantyla

3
Có lẽ tốt nhất để chạy lần đầu find . -name "*.pyc" -printvà chỉ sau đó xóa các tệp có vấn đề theo cách thủ công và / hoặc chạy lệnh ở trên, sau khi xác minh bạn không làm điều gì đáng tiếc.
michael

9
@DanMantyla Các gói nguồn đóng xứng đáng được xóa bằng mọi cách.
con mèo

25

Tải *.pyctập tin python3 được tạo bằng python2 cũng gây ra lỗi này.


3
Đây có thể là một bình luận, không phải là một câu trả lời.
Kroltan

2
@Kroltan nhưng nó là một câu trả lời tốt, tốt hơn so với câu trả lời. Súc tích và to-the-point.
Antony Hatchkins

@AntonyHatchkins Ít nhất theo quan điểm của tôi, đây có thể là một nhận xét về bất kỳ câu trả lời nào gợi ý xóa .pyc. Mặc dù đây là một nguyên nhân có thể , nhưng nó không có giải pháp khác , vì vậy điều này là dư thừa. Hãy đồng ý, chỉ là ý kiến ​​của tôi.
Kroltan

@Kroltan Phần 'cách khắc phục' khá rõ ràng ở đây. Nguyên nhân, đó là điều thực sự thú vị - ít nhất là đối với tôi - là. Tôi đã thực hiện rất nhiều thao tác với các phiên bản 2.x python khác nhau và không bao giờ gặp phải bất kỳ sự không tương thích nào giữa các phiên bản .pyc. Và giải pháp này cho biết đó là vấn đề python3 vs python2 - thông tin bị thiếu trong câu trả lời được chấp nhận. Thêm vào đó, tôi thích câu trả lời ngắn (nếu có thể) :)
Antony Hatchkins

@AntonyHatchkins, giải pháp này có thể nói đó là vấn đề py2 / 3 nhưng đó chỉ là một khả năng và, về vấn đề đó, một đề xuất trong câu trả lời được chấp nhận (đoạn 4) kể từ phiên bản đầu tiên của nó :-)
paxdiablo

6

Đưa tập tin pyc vào máy windows. Sử dụng bất kỳ trình soạn thảo Hex để mở tệp pyc này. Tôi đã sử dụng phần mềm miễn phí 'HexEdit'. Bây giờ đọc giá trị hex của hai byte đầu tiên. Trong trường hợp của tôi, đây là 03 f3.

Mở calc và chuyển đổi chế độ hiển thị của nó sang Lập trình viên (Khoa học trong XP) để xem chuyển đổi Hex và Decimal. Chọn "Hex" từ nút Radio. Nhập các giá trị dưới dạng byte thứ hai trước rồi đến byte đầu tiên tức là f303 Bây giờ bấm vào nút radio "Dec" (Decimal). Giá trị được hiển thị là một giá trị tương ứng với số ma thuật hay phiên bản python.

Vì vậy, xem xét bảng được cung cấp trong trả lời trước đó

  • 1.5 => 20121 => 4E99 vì vậy các tệp sẽ có byte đầu tiên là 99 và thứ hai là 4e
  • 1.6 => 50428 => C4FC để các tệp sẽ có byte đầu tiên là fc và thứ hai là c4

2

Lỗi "số ma thuật xấu" cũng xảy ra nếu bạn đã tự đặt tên tệp của mình bằng một phần mở rộng .pyc


1

Tôi đã gặp một trường hợp lạ về lỗi Số ma thuật xấu khi sử dụng cách triển khai (1.5.2) rất cũ. Tôi đã tạo một tệp .pyo và điều đó đã gây ra lỗi. Kỳ lạ thay, vấn đề đã được giải quyết bằng cách thay đổi tên của mô-đun. Tên vi phạm là sms.py. Nếu tôi đã tạo một sms.pyo từ mô-đun đó, lỗi Bad Magic Number là kết quả. Khi tôi đổi tên thành smst.py, lỗi đã biến mất. Tôi đã kiểm tra qua lại để xem sms.txt bằng cách nào đó đã can thiệp vào bất kỳ mô-đun nào khác có cùng tên nhưng tôi không thể tìm thấy bất kỳ xung đột tên nào. Mặc dù nguồn gốc của vấn đề này vẫn là một sự nhầm lẫn đối với tôi, tôi khuyên bạn nên thử thay đổi tên mô-đun.


1

Điều này cũng có thể là do thiếu __init__.pytập tin từ thư mục. Giả sử nếu bạn tạo một thư mục mới trong django để phân tách các bài kiểm tra đơn vị thành nhiều tệp và đặt chúng vào một thư mục thì bạn cũng phải tạo __init__.pytệp bên cạnh tất cả các tệp khác trong thư mục kiểm tra mới được tạo. nếu không nó có thể gây ra lỗi như 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'


0

Điều này là hiệu quả hơn nhiều so với ở trên.

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

đâu {directory-of-.pyc-files}là thư mục chứa các tập tin python đã biên dịch.


1
Đó là trong trường hợp bạn có các tập tin py trong tay, nếu không bạn sẽ cần phải hạ cấp cài đặt python.
Leon Fedotov

1
Điều này vẫn không an toàn cho một số trường hợp cạnh. Ngoài ra tại sao chúng ta thực hiện xóa đệ quy khi chúng ta đang nói về các tệp?
Jerome Baum

1
Tại sao bạn sử dụng hai quá trình? Ngay cả khi tìm thấy không xóa, bạn vẫn có thể chạyfind /dir -name "*.pyc" -exec rm '{}' ';'
mikemaccana

1
Lệnh 'find' sẽ không hoạt động an toàn cho tên tệp có khoảng trắng trong nếu toán tử cuối cùng mặc định được sử dụng trực tiếp bởi xargs rm. Python không nhập các tệp không có định danh như thế này, nhưng các tập lệnh vẫn có thể khiến tệp này bị hỏng và chúng sẽ không bị xóa. Nói chung luôn an toàn hơn khi sử dụng thêm -print0 (số 0 ở cuối) trên lệnh find (làm tham số cuối cùng trước ký hiệu ống '|') và sau đó tùy chọn -0 trên xargs (đó là dấu gạch nối + zero) để hiểu - đầu ra print0 trước lệnh rm, khi đường ống tìm vào xargs.
Breezer

0

Trong trường hợp của tôi, đó không phải là các tệp dịch .pycnhị phân cũ .mosau khi tôi đổi tên mô-đun của riêng mình, vì vậy trong thư mục mô-đun này, tôi phải chạy

find . -name \*.po -execdir sh -c 'msgfmt "$0" -o `basename $0 .po`.mo' '{}' \;

(vui lòng sao lưu và cố gắng sửa .pyctệp trước)


0

Điều này cũng có thể xảy ra nếu bạn có tệp python27.dll sai (trong trường hợp Windows), để giải quyết vấn đề này chỉ cần cài đặt lại (hoặc giải nén) python với phiên bản dll tương ứng chính xác. Tôi đã có một kinh nghiệm tương tự.


0

Tôi vừa gặp vấn đề tương tự với Fedora26 khi nhiều công cụ như dnf bị hỏng do số ma thuật xấu trong sáu. Vì một lý do không xác định, tôi đã có một tập tin /usr/bin/six.pyc, với số ma thuật bất ngờ. Xóa tập tin này khắc phục sự cố


0

Trong trường hợp của tôi, tôi có git clonemột lib có thông dịch viên

#!/usr/bin/env python

Mặc dù pythonđã dẫn đến Python2.7mặc dù mã chính của tôi đang chạy với python3.6 ... nó vẫn tạo một *.pyctệp cho 2.7phiên bản ...

Tôi có thể nói rằng lỗi này có thể là kết quả của sự pha trộn giữa các phiên bản 2.7 & 3+, đây là lý do tại sao dọn dẹp (theo bất kỳ cách nào bạn có thể nghĩ về việc bạn đang sử dụng) - sẽ giúp ích ở đây ...

  • đừng quên điều chỉnh mã Python2x -> python 3 ...

-1

Đừng xóa chúng !!! Cho đến khi ..........

Tìm một phiên bản trên thư mục git, svn hoặc sao chép của bạn hoạt động.

Xóa chúng và sau đó phục hồi tất cả .pyc.

Đó là công việc cho tôi.


tại sao tôi có -1? nó thực sự hiệu quả với tôi và tôi đã ở trong tình huống thực sự tồi tệ
lauralacarra

2
trở lại phiên bản trước không phải là một giải pháp toàn cầu
ZiTAL

4
Tại sao bạn bao giờ cam kết các *.pyctập tin của bạn ?
Manos Kounelakis

Đó là lỗi thông thường. Khi bạn không cấu hình tệp git bỏ qua chính xác. Vì vậy, tôi đưa ra giải pháp và sau đó bạn phải đặt hàng git của bạn.
lauralacarra

-1

Bạn sẽ cần chạy lệnh này trong mọi đường dẫn bạn có trong môi trường của mình.

>>> import sys
>>> sys.path
['', '/usr/lib/python36.zip', '/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload', '/usr/local/lib/python3.6/dist-packages', '/source_code/src/python', '/usr/lib/python3/dist-packages']

Sau đó chạy lệnh trong mọi thư mục ở đây

find /usr/lib/python3.6/ -name "*.pyc" -delete
find /usr/local/lib/python3.6/dist-packages -name "*.pyc" -delete
# etc...
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.