2010-02-14 66 views
17

Một thời gian trước, tôi phải nâng cấp một số máy chủ từ Python 2.4 lên Python 2.5. Tôi thấy rằng các tệp .pyc được tạo trong Python 2.4 sẽ bị lỗi khi Python 2.5 cố gắng chạy chúng.Các tệp Python 2.5 .pyc có tương thích với các tệp Python 2.6 .pyc không?

Điều này có xảy ra khi tôi nâng cấp từ 2,5 lên 2,6 không?

EDIT: Dưới đây là chi tiết hơn một chút

Tôi có một máy chủ tệp chứa mã python. Điều này được truy cập bởi cả hai máy chủ Ubuntu và Windows để chạy mã python. Khi họ chạy mã, họ tạo ra các tệp .pyc trên máy chủ tệp.

Tôi thấy rằng khi tôi nâng cấp một trong các máy chủ từ Python 2.4 lên 2.5, tôi gặp sự cố với tệp .pyc. Bây giờ tôi không chắc liệu đó là một máy chạy 2.5 đã cố gắng chạy bytecode 2.4 hay cho dù đó là một máy 2.4 cố gắng chạy 2.5 bytecode, nhưng nếu tôi đã xóa bytecode thì mọi thứ đều ổn cho đến khi xung đột bytecode tiếp theo.

Tôi đã nâng cấp tất cả các máy lên 2.5 và sự cố đã biến mất.

Trả lời

13

Nói chung, .pyc tập tin được cụ thể cho một phiên bản Python (mặc dù di động trên các kiến ​​trúc máy khác nhau, miễn là chúng đang chạy cùng một phiên bản); các tệp này chứa thông tin về phiên bản Python có liên quan trong tiêu đề của chúng - vì vậy, nếu bạn để các tệp .py tương ứng bên cạnh các số .pyc, thì .pyc sẽ được xây dựng lại mỗi khi một phiên bản Python khác được sử dụng để nhập các mô-đun đó."Đang cố chạy" các tập tin .pyc sai là một cái gì đó mà tôi chưa từng nghe đến. Kiến trúc nào đã được tham gia? Có phải các tệp .py xung quanh chúng phải không?

Sửa: như OP làm rõ rằng tai nạn đến khi ông được chạy cả hai Python 2.4 Python 2.5 chương trình trên cùng một .py file (từ hai máy chủ khác nhau, chia sẻ một ổ đĩa mạng), giải thích của tai nạn trở nên dễ dàng. Các tập tin .py là tất cả thời gian được biên dịch lại - bởi 2.4 Python khi 2.5 đã là một trong những chạy chúng gần đây nhất, và ngược lại - và do đó các tập tin .pyc đã điên cuồng bận rộn nhận được viết lại tất cả các thời gian. Khóa tập tin thích hợp trên ổ đĩa mạng (đặc biệt nhưng không độc quyền trên các hệ điều hành khác nhau) nổi tiếng là khó đạt được. Vì vậy, những điều sau đây phải xảy ra (các vai trò có thể được chuyển đổi): máy chủ 2.4 vừa xác định rằng tệp .pyc là tốt cho nó và bắt đầu đọc nó; trước khi nó có thể đọc xong, máy chủ 2.5 (trước đây đã xác định rằng mô-đun cần được biên dịch lại) đã ghi đè lên nó; do đó, máy chủ 2.4 đã kết thúc với bộ nhớ đệm có (nói) 4K byte đầu tiên từ phiên bản 2.4 và 4K byte tiếp theo từ phiên bản 2.5. Khi đó, sử dụng bộ đệm bị xáo trộn, không đáng ngạc nhiên ... lỗi !!! Điều này có thể là một vấn đề thực sự nếu bạn thấy mình liên tục cố gắng chạy một tập hợp đơn lẻ của .py tệp từ hai hoặc nhiều phiên bản Python khác nhau (ngay cả trên cùng một máy chủ, mà không có biến chứng thêm của ổ đĩa mạng). Quay lại đầu trang Giải pháp "thích hợp" sẽ là một cái gì đó như virtualenv. Đòn tấn công (đơn giản nhưng bẩn thỉu) mà chúng tôi đã sử dụng tại nơi làm việc (nhiều năm trước, nhưng nó vẫn còn trong sản xuất ...!) Là vá từng phiên bản của Python để tạo và sử dụng một phần mở rộng khác cho các tệp bytecode được biên dịch của nó: .pyc (hoặc .pyo) cho Python 1.5.2 (phiên bản "hệ thống" ổn định nhất khi chúng tôi bắt đầu thực hiện phiên bản mới này), .pyc-2.0 cho 2.0, .pyc-2.2 cho 2.2 và vv (hoặc tương đương .pyo-X.Y tất nhiên). Tôi nghe nói điều này sẽ sớm biến mất trong thời gian dài (cảm ơn Thomas!), Nhưng nó đã khiến chúng tôi phải lo lắng về vấn đề này trong nhiều năm.

Một giải pháp đơn giản hơn nhiều là giữ một phiên bản Python xung quanh, nếu đó là khả thi cho hệ thống của bạn; nếu hệ thống của bạn có bất kỳ biến chứng nào làm cho nó không khả thi để có một phiên bản Python (như của chúng ta đã làm, và), thì những ngày này tôi chân thành khuyên bạn nên virtualenv, mà tôi đã đề cập.

+0

Đôi khi mọi người cố gắng phân phối các tệp .pyc không có tệp .py dưới dạng hình thức bảo vệ IP. –

+0

@gnibbler: Vâng, nhưng điều đó thật ngu ngốc, vì các tệp .pyc rất dễ đọc và dễ dàng giải mã được với một đại diện rất gần như – nosklo

+0

Cảm ơn vì điều đó. Tôi ngạc nhiên bởi lỗi khóa tập tin. Điều đó có nghĩa là tôi không thể nâng cấp từ python 2.5 lên 2.6 một máy chủ cùng một lúc, nhưng phải mang tất cả xuống và nâng cấp tất cả chúng trước khi đưa chúng trở lại. – pwdyson

2

Phiên bản Python tạo tệp được lưu trữ trong tệp .pyc. Thông thường điều này có nghĩa rằng pyc được thay thế bởi một với phiên bản Python đúng

một số lý do này có thể không xảy ra
- quyền
- tập tin py không có sẵn

Trong trường hợp vấn đề cho phép , Python sẽ chỉ cần sử dụng py và bỏ qua những pyc (với chi phí để thực hiện)

tôi nghĩ rằng đó là ok giữa các phiên bản nhỏ mặc dù, ví dụ như một Python2.6.2 pyc nên làm việc với Python2.6.4

Dưới đây là một đoạn trích từ/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 

Vì vậy, bạn có thể thấy rằng phiên bản Python đúng được chỉ định bởi 4 byte đầu tiên của file pyc

+0

Điều đó có nghĩa là .py không khả dụng. – nosklo

0

Bạn chắc chắn sẽ cần để biên dịch lại các tập tin bytecode cho chúng được sử dụng bất kỳ. Số ma thuật bytecode đã thay đổi trên mọi phiên bản chính của Python (*).

Tuy nhiên, việc có các tệp bytecode không khớp với phiên bản không được gặp sự cố Python. Nó thường sẽ bỏ qua bất kỳ bytecode nào không có số phiên bản chính xác, vì vậy không nên có lỗi, nó sẽ chậm hơn lần đầu tiên khi nó biên dịch lại (hoặc chậm hơn mỗi lần nếu người dùng chạy tập lệnh không không có quyền ghi để cập nhật bytecode).

(*:.. Và thường xuyên trong các giai đoạn phát triển, cộng thêm trong các phiên bản trước đó đôi khi nó thay đổi theo phiên bản nhỏ quá Xem import.c để có danh sách đầy đủ các con số ma thuật và các phiên bản Python tương ứng của họ)

5

Nếu bạn có mã nguồn thì nó sẽ biên dịch lại cho bạn. Vì vậy, nói chung bạn không sao.

Nhưng, điều này có thể không tốt cho bạn nếu người dùng có các phiên bản Python khác nhau chạy từ thư mục cài đặt trung tâm.

Nó cũng có thể tệ nếu bạn chỉ có tệp pyc. Tôi chỉ chạy một bài kiểm tra nhanh cho bạn. Tôi đã tạo hai tệp .pyc. Một trong 2.5 và một trong 2.6. 2.5 sẽ không chạy ở 2.6 và 2.6 sẽ không chạy ở 2.5. Cả hai đều ném lỗi "ImportError: Bad magic number in ..", điều này có ý nghĩa vì số ma thuật đã thay đổi từ 2,5 đến 2,6.

Nếu bạn muốn xác định trước đây về thời gian bạn có thể lấy con số kỳ diệu của Python của bạn như sau:

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

Để có được con số kỳ diệu cho một tập tin PYC bạn có thể làm như sau:

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

Bạn có thể mở rộng khi điều này? Bởi vì đó là tình huống: "Nhưng, điều này có thể không tốt cho bạn nếu người dùng có các phiên bản Python khác nhau chạy từ một kho mã trung tâm." – pwdyson

+0

Chắc chắn. Nếu trước tiên chúng ta giả định rằng một người có Python 2.5 đã sử dụng kho lưu trữ các pycs sẽ là 2,5 pycs. Khi một người dùng Python 2.6 sử dụng kho lưu trữ, họ sẽ chuyển đổi các pycs của các tệp họ nhập vào 2.6 pycs. Họ cũng sẽ đạt tốc độ để thực hiện nó. Bạn cũng có thể gặp vấn đề nếu những người có phiên bản khác nhau cố gắng sử dụng các pycs cùng một lúc. Chỉ cần rõ ràng kho lưu trữ này mà tôi nói là nơi mọi người đang chạy mã không kiểm tra mã vào và ra. –

+0

Tôi đã chỉnh sửa câu trả lời gốc và thay đổi thuật ngữ "kho lưu trữ" thành "thư mục cài đặt" để đảm bảo rằng tôi đã rõ ràng. –

Các vấn đề liên quan