2014-05-21 20 views
15

Tôi biết rằng tệp .pyc được tạo bởi trình thông dịch python và chứa mã byte như thế này question cho biết.Trình thông dịch python biết khi biên dịch và cập nhật tệp .pyc như thế nào?

Tôi nghĩ trình thông dịch python đang sử dụng dấu thời gian để phát hiện xem .pyc có mới hơn .py hay không và bỏ qua khi biên dịch lại khi thực thi. (Cách thức makefile làm)

Vì vậy, tôi đã làm một thử nghiệm, nhưng có vẻ như tôi đã sai.

  1. tôi đã viết t.py chứa và t1.py chứa import t. Lệnh chạy python t1.py cho kết quả 123 và được tạo t.pyc, tất cả như mong đợi.
  2. Sau đó, tôi đã chỉnh sửa t.py làm print '1234' và cập nhật dấu thời gian của t.pyc bằng cách sử dụng touch t.pyc.
  3. Chạy python t1.py một lần nữa, tôi nghĩ tôi sẽ nhận được 123 nhưng 1234 thực sự. Vì vậy, có vẻ như thông dịch viên trăn vẫn biết rằng t.py được cập nhật.

Sau đó, tôi tự hỏi liệu trình thông dịch python sẽ biên dịch và tạo t.pyc mỗi lần chạy python t1.py. Nhưng khi tôi chạy python t1.py nhiều lần, tôi thấy rằng t.pyc sẽ không được cập nhật khi t.py không được cập nhật.

Vì vậy, câu hỏi của tôi là: cách trình thông dịch python biết khi nào biên dịch và cập nhật tệp .pyc?

Cập nhật

Từ trăn dịch viên đang sử dụng dấu thời gian lưu trữ trong tập tin .pyc. Tôi nghĩ rằng đó là một bản ghi khi .pyc được cập nhật lần cuối. Và khi được nhập, hãy so sánh nó với dấu thời gian của tệp .py.

Vì vậy, tôi đã cố gắng để hack nó theo cách này: thay đổi thời gian hệ điều hành để một cũ hơn, và chỉnh sửa .py tập tin. Tôi nghĩ khi được nhập lại, .py có vẻ cũ hơn .pyc và trình thông dịch trăn sẽ không cập nhật .pyc. Nhưng tôi lại sai.

Vì vậy, trình thông dịch python có so sánh hai dấu thời gian này không theo cách cũ hơn hoặc mới hơn nhưng theo cách chính xác không?

Trong một cách exectly bình đẳng, tôi có nghĩa là dấu thời gian trong .pyc ghi lại khi .py được sửa đổi lần cuối. Khi được nhập, nó so sánh dấu thời gian với dấu thời gian hiện tại của .py, nếu nó không giống nhau, biên dịch lại và cập nhật .pyc.

+0

@JonathonReinhart: Tôi muốn nói trùng lặp thực sự, đặc biệt vì câu hỏi đó chứa câu trả lời: Dấu thời gian được tư vấn là không phải dấu thời gian của hệ thống tệp, nhưng dấu thời gian nội bộ được lưu trữ trong tệp '.pyc'. –

+0

@TimPietzcker Đồng ý, đó chỉ là nhận xét được tạo tự động. Nếu tôi chỉ có một trong số họ * có huy hiệu vàng lạ mắt * Tôi sẽ đánh dấu nó trùng lặp ngay lập tức :-) –

+2

Tuy nhiên, +1 cho câu hỏi, vì nỗ lực sáng tạo đã đi vào nó - tôi chưa bao giờ nghĩ về điều gì xảy ra nếu bạn sửa đổi dấu thời gian của tệp. –

Trả lời

4

Dường như dấu thời gian được lưu trữ trực tiếp trong tệp *.pyc. Trình thông dịch python không dựa vào thuộc tính sửa đổi cuối cùng của tệp, có thể để tránh các vấn đề bytecode không tương thích khi sao chép các cây nguồn.

Nhìn vào the python implementation of the import statement, bạn có thể tìm séc cũ trong _validate_bytecode_header(). Bằng vẻ ngoài của nó, nó trích xuất các byte từ 4 đến 7 (bao gồm) và so sánh nó với mã thời gian của tệp nguồn. Nếu những người không khớp, mã byte được coi là bị trì hoãn và do đó được biên dịch lại.

Trong quá trình này, nó cũng kiểm tra độ dài của tệp nguồn dựa trên độ dài của nguồn được sử dụng để tạo ra bytecode đã cho (được lưu trữ trong byte 8 đến 11).

Trong triển khai python, nếu một trong những kiểm tra đó không thành công, trình tải byte bytecode tăng ImportError được bắt bằng SourceLoader.get_code() kích hoạt biên dịch lại bytecode.

Lưu ý: Đó là cách thực hiện trong phiên bản python importlib. Tôi đoán không có sự khác biệt về chức năng trong phiên bản gốc, nhưng C của tôi hơi bị đào sâu vào mã trình biên dịch

+0

Cảm ơn bạn đã liên kết mã, nó trợ giúp. '_r_long (raw_timestamp)! = source_mtime' hiển thị so sánh dấu thời gian tương tự như tôi đoán :) – WKPlus

+0

Có thể chính xác hơn" nếu những thứ đó không khớp ", điều đó chắc chắn ;-) – svvac

0

Như bạn nghĩ, nó có hiệu quả dựa trên dấu thời gian của bản cập nhật .py cuối cùng.Nếu .py đã được cập nhật sau khi tạo thế hệ .pyc, mã bytecode sẽ được tạo lại. Đó là hành vi tương tự hơn make (chỉ biên dịch lại các tệp mới).

.pyc được cập nhật nếu bạn nhập mô-đun, vì vậy kiểm tra của bạn không hoạt động vì bạn đã thực thi mã, không nhập mã tôi tin.

+0

Nhưng làm thế nào để giải thích kết quả thử nghiệm cuối cùng của tôi? – WKPlus

+0

Tôi đã cập nhật câu trả lời của mình;) –

+0

Tôi đã nhập nó không thực hiện nó :) – WKPlus

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