2014-05-21 32 views
15

我知道,一個.pyc文件是由Python解釋器產生和包含字節代碼,因爲這question說。python解釋器如何知道何時編譯和更新.pyc文件?

我以爲Python解釋器正在使用時間戳來檢測.pyc是否比.py更新,如果是,跳過執行時再次編譯它。 (什麼makefile文件這樣做的方式)

所以,我做了一個測試,但它似乎我錯了。

  1. 我寫t.py包含和t1.py包含import t。運行命令python t1.py給輸出123和產生t.pyc ,所有的預期。
  2. 然後我編輯t.pyprint '1234',並通過使用更新touch t.pyct.pyc時間戳。
  3. 再次運行python t1.py,我想我會得到123,但確實是1234 。所以似乎python解釋器仍然知道t.py 已更新。

然後我不知道Python解釋器是否會編譯生成t.pyc運行python t1.py每次。但是,當我運行python t1.py好幾次,我發現,當不更新t.pyt.pyc將不會被更新。

所以,我的問題是:Python解釋器如何知道什麼時候來編譯和更新.pyc文件?

更新

因爲Python解釋器使用存儲在.pyc文件的時間戳。我認爲這是.pyc最後更新時間的記錄。並且在導入時,將其與.py文件的時間戳進行比較。

於是,我就砍它是這樣的:改變操作系統的時間一老一,和編輯.py文件。 我想當再次導入時,.py似乎比.pyc更早,並且python解釋器不會更新.pyc但我錯了。

那麼,python解釋器是不是比較這兩個時間戳不是以一種更老或更新的方式,而是以完全相同的方式?

以非常相似的方式,我的意思是.pyc中的時間戳記錄了.py上次修改時間。導入時,它會將時間戳與.py的當前時間戳進行比較,如果不相同,請重新編譯並更新.pyc

+0

@JonathonReinhart:我會說實際的重複,尤其是因爲該問題包含答案:參考的時間戳是不是文件系統的時間戳,而是存儲在'.pyc'文件中的內部時間戳。 –

+0

@TimPietzcker同意,這只是自動生成的評論。如果只有我有一個*他們那裏花式金徽章*我會立即標記它複製:-) –

+2

仍然,+1,因爲它的創造性努力 - 我從來沒有想過會發生什麼如果你修改文件的時間戳。 –

回答

4

它看起來像時間戳記直接存儲在*.pyc文件中。 python解釋器不依賴於文件的最後一個修改屬性,也許爲了避免複製源樹時出現不兼容的字節碼問題。

看着the python implementation of the import statement,你可以在_validate_bytecode_header()找到陳舊的支票。從外觀上看,它提取字節4到7(含)並將其與源文件的時間碼進行比較。如果那些不匹配,字節碼被認爲是停滯的並因此被重新編譯。

在此過程中,它還會根據用於生成給定字節碼的源的長度(存儲在字節8至11中)檢查源文件的長度。

在python實現中,如果其中一個檢查失敗,字節碼加載程序會引發一個ImportError,由SourceLoader.get_code()捕獲,觸發重新編譯字節碼。

注意:這就是它在importlib的python版本中的工作方式。我猜在本地版本中沒有函數的區別,但是我的C有點太生鏽,無法深入編譯器代碼

+0

感謝代碼鏈接,它確實有所幫助。 '_r_long(raw_timestamp)!= source_mtime'顯示時間戳比較與我猜對的方式相同:) – WKPlus

+0

可能比「如果那些不匹配」更精確,這是肯定的;-) – svvac

0

如您所知,它基於最新.py更新的時間戳。如果.py已經更新之後.pyc的生成,字節碼將被重新生成。這與make(僅重新編譯新文件)的行爲相同。

如果您要導入模塊,則會更新.pyc,因此您的測試未能正常工作,因爲您執行了代碼,而不是導入它。

+0

但如何解釋我的最終測試結果? – WKPlus

+0

我已經更新了我的答案;) –

+0

我正在導入它不執行它:) – WKPlus

相關問題