2013-04-05 35 views
64

Tôi hiểu rằng tệp ".pyc" được biên dịch phiên bản của tệp ".py" thuần văn bản, được tạo khi chạy để làm cho chương trình chạy nhanh hơn. Tuy nhiên, tôi đã quan sát một vài điều:Khi nào các tệp .pyc được làm mới?

  1. Khi sửa đổi tệp "py", thay đổi hành vi của chương trình. Điều này chỉ ra rằng các tập tin "py" được biên dịch hoặc ít nhất là mặc dù một số loại quá trình băm hoặc so sánh tem thời gian để cho biết liệu chúng có nên được biên dịch lại hay không.
  2. Khi xóa tất cả các tệp ".pyc" (rm *.pyc) đôi khi hành vi của chương trình sẽ thay đổi. Mà sẽ chỉ ra rằng họ không được biên dịch trên cập nhật của ".py" s.

Câu hỏi:

  • Làm thế nào để họ quyết định khi nào thì được biên dịch?
  • Có cách nào để đảm bảo rằng họ có kiểm tra chặt chẽ hơn trong quá trình phát triển không?
+10

Cẩn thận với xóa pyc file với 'rm * .pyc'. Thao tác này sẽ không xóa các tệp .pyc trong các thư mục lồng nhau. Sử dụng 'tìm. -name '* .pyc' -delete' thay vì – Zags

+4

Có lẽ một lưu ý về câu hỏi của bạn: Chương trình không chạy nhanh hơn khi được đọc từ tệp '.pyc' hoặc '.pyo' hơn khi được đọc từ tập tin '.py'; điều duy nhất nhanh hơn về các tệp ‘.pyc’ ​​hoặc ‘.pyo’ là tốc độ tải chúng. [link] (http://www.network-theory.co.uk/docs/pytut/CompiledPythonfiles.html) – maggie

+0

@maggie sự khác biệt giữa thời gian tải và thời gian thực hiện là gì? –

Trả lời

53

Tệp .pyc được tạo (và có thể ghi đè) chỉ khi tệp python đó được nhập bởi một số tập lệnh khác. Nếu quá trình nhập được gọi, Python sẽ kiểm tra xem dấu thời gian nội bộ của tệp .pyc có khớp với tệp .py tương ứng không. Nếu có, nó sẽ tải .pyc; nếu nó không hoặc nếu .pyc chưa tồn tại, Python sẽ biên dịch tệp .py thành một .pyc và tải nó.

Bạn có ý nghĩa gì khi "kiểm tra chặt chẽ hơn"?

+3

Tôi có thể khắc phục sự cố với 'rm * .pyc'. Tôi biết rằng nếu tôi buộc tất cả các tệp sẽ được tạo lại thì một số vấn đề đã được khắc phục, cho biết rằng các tệp đó không được tự biên dịch lại. Tôi cho rằng nếu họ sử dụng các dấu thời gian thì không có cách nào để làm cho hành vi này chặt chẽ hơn, nhưng vấn đề vẫn còn tồn tại. –

+10

Điều này không hoàn toàn chính xác. Dấu thời gian không cần phải khớp (và thường thì không). Dấu thời gian '.pyc' phải * cũ hơn * dấu thời gian' .py' tương ứng để kích hoạt biên dịch lại. –

+0

@TimPietzcker Ah, tất nhiên là có ý nghĩa. Tốt để biết. Và OP, cũng có các loại tệp khác có thể được nhập bằng Python. Một '.so', ví dụ, là một phần mở rộng C được biên dịch có thể được gọi bởi Python như thể nó là một tệp' .pyc'. Ngoài ra tôi cần thêm chi tiết về vấn đề của bạn để cung cấp bất cứ điều gì khác. – DaveTheScientist

21

tệp .pyc được tạo bất cứ khi nào các phần tử mã tương ứng được nhập và cập nhật nếu các tệp mã tương ứng đã được cập nhật. Nếu các tệp .pyc bị xóa, chúng sẽ tự động được tạo lại. Tuy nhiên, chúng được không tự động xóa khi các tệp mã tương ứng bị xóa.

Điều này có thể gây ra một số lỗi thực sự thú vị trong các trình tái cấu trúc cấp tệp.

Trước hết, bạn có thể kết thúc đẩy mã chỉ hoạt động trên máy của bạn và không phải của người khác. Nếu bạn có các tham chiếu lơ lửng đối với các tệp bạn đã xóa, các tệp này sẽ vẫn hoạt động cục bộ nếu bạn không xóa các tệp .pyc có liên quan do tệp .pyc có thể được sử dụng trong nhập. Điều này là phức tạp với thực tế là một hệ thống điều khiển phiên bản được cấu hình đúng sẽ chỉ đẩy các tệp .py vào kho lưu trữ trung tâm, chứ không phải tệp .pyc, có nghĩa là mã của bạn có thể vượt qua "kiểm tra nhập" (mọi thứ đều ổn) chỉ tốt và không làm việc trên máy tính của người khác.

Thứ hai, bạn có thể có một số lỗi khá khủng khiếp nếu bạn chuyển các gói thành mô-đun. Khi bạn chuyển đổi một gói (một thư mục có tệp __init__.py) thành một mô-đun (tệp .py), tệp .pyc đã từng đại diện cho gói đó vẫn còn. Cụ thể, __init__.pyc vẫn còn. Vì vậy, nếu bạn có foo gói với một số mã mà không quan trọng, sau đó xóa gói đó và tạo ra một foo.py tập tin với một số chức năng def bar(): pass và chạy:

from foo import bar 

bạn nhận được:

ImportError: cannot import name bar 

vì python vẫn đang sử dụng tệp .pyc cũ từ gói foo, không có thanh nào trong số đó xác định thanh.Điều này có thể đặc biệt có vấn đề trên máy chủ web, nơi mã hoạt động hoàn toàn có thể bị hỏng do tệp .pyc.

Theo kết quả của cả những lý do này (và có thể những người khác), mã triển khai của bạn và mã thử nghiệm nên xóa file pyc, chẳng hạn như với các dòng sau của bash:

find . -name '*.pyc' -delete 

Ngoài ra, tính đến python 2.6, bạn có thể chạy python với cờ -B để không sử dụng các tệp .pyc. Xem How to avoid .pyc files? để biết thêm chi tiết.

Xem thêm: How do I remove all .pyc files from a project?

+0

"Khi bạn chuyển đổi một mô-đun (một thư mục có tệp' __init __. Py') ... ". Đó sẽ là một gói, không phải là một mô-đun. –

+0

@RobertDavidĐiểm tốt; sửa đổi – Zags

+2

* Đặc biệt, '__init __. pyc' vẫn còn. * - Làm cách nào? Là một gói là một thư mục xóa một gói có nghĩa là xóa thư mục do đó không có tệp nào còn lại… –

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