2010-04-08 88 views
42

我有一個名爲foobar(不帶.py擴展名)的文件。在同一目錄中我試圖將其導入另一個Python文件:導入不帶.py擴展名的python模塊

import foobar 

但是,如果我重新命名爲foobar.py文件這僅適用。是否有可能導入一個沒有.py擴展名的python模塊?

更新:該文件沒有擴展名,因爲我也將其用作獨立腳本,並且我不想輸入.py擴展名來運行它。

更新2:我將採用下面提到的符號鏈接解決方案。

+1

我好奇。爲什麼你有沒有'py'擴展名的python文件? – voyager 2010-04-08 16:52:43

+1

有時,使用python作爲配置文件(擴展名爲.conf)或表示特殊類型的文件是很好的做法。就我而言,這對管理員來說更方便。 – NuclearPeon 2013-08-02 03:01:01

+1

我有一個配置文件,既用作python文件又用作bash腳本。我給了它一個'pysh'的擴展...... – osa 2014-07-11 21:43:55

回答

31

您可以使用imp.load_source函數(來自imp模塊)從給定文件系統路徑動態加載模塊。

foobar = imp.load_source('foobar', '/path/to/foobar') 

這個SO discussion也顯示了一些有趣的選項。

+0

已修復。 [雖然建議編輯更具建設性] – 2015-05-14 14:02:05

+0

但是我需要的部分是 >>> foobar = imp.load_source('','credentials') [默認] NameError:name'default'未定義 – Ilja 2015-10-11 10:16:14

+2

如果在返回值中分配了第一個參數「foobar」,那麼它有什麼用? – 2016-04-30 14:13:27

13

imp.load_source(module_name, path)應該做的,或者如果你有一個文件句柄,而不是

13

像其他人所說的,你可以使用imp.load_source你可以做更詳細的imp.load_module(module_name, file_handle, ...)路線,但它會使你的代碼更難以閱讀。如果需要在運行時導入名稱或路徑未知的模塊,我真的只會推薦它。

你不想使用.py擴展名的原因是什麼?不希望使用.py擴展名的最常見情況是因爲python腳本也作爲可執行文件運行,但您仍然希望其他模塊能夠導入它。如果是這種情況,將功能移入具有相似名稱的.py文件可能會有所幫助,然後使用foobar作爲包裝。

+12

或者不是包裝,只是符號鏈接foobar.py foobar(假設你不在Windows上) – whaley 2010-04-08 18:31:15

+0

@whaley,是的,這將是更清潔。你可以使用Windows的.bat來完成同樣的事情。 – 2010-04-08 22:45:08

+0

我有一個整潔的用例 - 一個自述文件,裏面有例子,我想用doctest來驗證。我希望能夠製作一個doctest markdown文檔... – 2011-11-24 23:05:31

1

如果您安裝與包管理器腳本(DEB或類似),另一種選擇是使用setuptools的:

"...there’s no easy way to have a script’s filename match local conventions on both Windows and POSIX platforms. For another, you often have to create a separate file just for the 「main」 script, when your actual 「main」 is a function in a module somewhere... setuptools fixes all of these problems by automatically generating scripts for you with the correct extension, and on Windows it will even create an .exe file..."

https://pythonhosted.org/setuptools/setuptools.html#automatic-script-creation

4

這裏就是Python 3.4+的解決方案:

from importlib.util import spec_from_loader, module_from_spec 
from importlib.machinery import SourceFileLoader 

spec = spec_from_loader("foobar", SourceFileLoader("foobar", "/path/to/foobar")) 
foobar = module_from_spec(spec) 
spec.loader.exec_module(foobar) 

使用spec_from_loader並明確指定SourceFileLoader將強制machinery加載文件a而不是試圖從擴展中找出文件的類型。這意味着您可以加載該文件,即使它未在importlib.machinery.SOURCE_SUFFIXES中列出。

如果你想保持進口按名稱的文件的第一個負載後,將模塊添加到sys.modules

sys.modules['foobar'] = foobar