2011-12-07 44 views
4

我需要通過文件路徑導入python模塊(例如,「/some/path/to/module.py」),只在運行時知道並忽略任何.pyc文件存在。強制python從文件路徑動態加載模塊時忽略pyc文件

這個previous question建議使用imp.load_module作爲解決方案,但是這種方法如果存在的話也會使用.pyc版本。

importme.py

SOME_SETTING = 4 

main.py:

import imp 
if __name__ == '__main__': 
    name = 'importme' 
    openfile, pathname, description = imp.find_module(name) 
    module = imp.load_module(name, openfile, pathname, description) 
    openfile.close() 
    print module 

執行兩次,.pyc文件首先調用後使用:

$ python main.py 
<module 'importme' from '/Users/dbryant/temp/pyc/importme.py'> 

$ python main.py 
<module 'importme' from '/Users/dbryant/temp/pyc/importme.pyc'> 

Unfortun ately,imp.load_source具有相同的行爲(從文檔):

注意,如果正確匹配字節編譯的文件(後綴爲.pyc文件 或.pyo)存在,它將用來代替解析給定的來源 文件。

製作包含腳本的目錄只讀的是,我所知道的(防止產生.pyc文件擺在首位),但如果可能的話,我寧願避免它的唯一解決方案。

(注:使用Python 2.7)

+1

爲什麼要防止使用pyc文件?它只會使用pyc文件,如果它與py相同。如果你改變py,它會重新編譯pyc。 – Falmarri

+0

@Falmarri這很複雜。它與不同類型的機器訪問相同的一組python文件有關,它們似乎產生了相同源代碼的不兼容的字節彙編(例如,機器A生成的pyc不能被機器B讀取,導致機器B無法動態地導入模塊);是的,所有機器都使用解釋器二進制。 – awesomo

+0

不同機器編寫不同字節碼的唯一原因是它們運行不同版本的解釋器。 – limscoder

回答

0

如何使用含蟒蛇來源,而不是zip文件:

import sys 
sys.path.insert("package.zip") 
+0

有趣,但對我的用例來說效果並不理想。我動態加載的模塊是設置文件,需要易於閱讀和編輯。 – awesomo

+2

你也可以看看使用PYTHONDONTWRITEBYTECODE環境變量。 –

+0

好點。這也會起作用,但唯一導致問題的pyc文件是那些用'imp'動態加載的文件,我希望能夠在所有其他東西可用時仍然使用字節碼版本。 – awesomo

0

你可以標記包含.py文件爲只讀的目錄。

+0

是的,我知道(請參閱問題的底部),但這並不是真正解決問題,而且非常不方便,因爲我確實需要仍然寫入包含日誌,輸出等的目錄。 – awesomo

+0

我不知道你確切的情況是,但我通常會盡量避免將數據寫入包含代碼的同一目錄。 – limscoder

+0

我原則上同意,但在這種情況下Python設置文件模糊了數據和代碼之間的界限(例如在Django中很常見的做法) – awesomo

2

load_source做正確的事情對我來說,即

dir, name = os.path.split(path) 
mod = imp.load_source(name, path) 

使用即使PYC文件可在變異的.py - 名.py下python3結束。顯而易見的解決方案顯然是在加載文件之前刪除所有.pyc文件 - 儘管運行多個程序實例,但競態條件可能會成爲問題。

另一種可能性:Iirc可以讓Python從內存中解釋文件 - 即使用正常的文件API加載文件,然後編譯內存中的變體。例如:

path = "some Filepath.py" 
with open(path, "r", encoding="utf-8") as file: 
    data = file.read() 
exec(compile(data, "<string>", "exec")) # fair use of exec, that's a first! 
+0

不錯,我甚至沒有考慮執行設置文件/模塊內容。這對我來說也是一個可行的解決方案。 – awesomo