2009-11-03 37 views
4

(重要提示:請參閱下面更新。)的Python:通過功能導入到主命名空間

我試圖寫一個函數,import_something,這將重要的某些模塊。 (這個問題對於哪個問題無關緊要。)問題是,我希望這些模塊能夠在函數被調用的級別導入。例如:

import_something() # Let's say this imports my_module 
my_module.do_stuff() # 

這可能嗎?

更新:

對不起,我原來的措辭和示例進行了誤導。我會盡力解釋我的整個問題。我擁有的是一個包,裏面有一些模塊和包。在其__init__.py我想導入所有的模塊和包。因此,在程序的其他地方,我導入整個包,並遍歷它所導入的模塊/包。

(爲什麼?包名爲crunchers,和裏面有定義各種統計員,像CruncherThreadCruncherProcess,並在未來或許MicroThreadCruncher。我希望統計員包自動都被放置在統計員在後面的程序中,當我使用crunchers時,我知道它可以確切地說明我已經定義了哪些crunchers。)

我知道如果我完全避免使用函數,並且執行main級別爲for循環等。但它很醜,我想看看我能否避免它。

如果還有什麼不清楚的地方,請在評論中提問。

回答

4

函數能夠將某些東西返回到它們被調用的地方。它被稱爲他們的回報價值:p

def import_something(): 
    # decide what to import 
    # ... 
    mod = __import__(something) 
    return mod 
my_module = import_something() 
my_module.do_stuff() 

好風格,沒有麻煩。

關於您的更新,我想加入這樣的事情你__init__.py你想要做什麼:

import os 

# make a list of all .py files in the same dir that dont start with _ 
__all__ = installed = [ name for (name,ext) in (os.path.splitext(fn) for fn in os.listdir(os.path.dirname(__file__))) if ext=='.py' and not name.startswith('_') ] 
for name in installed: 
    # import them all 
    __import__(name, globals(), locals()) 

別的地方:

import crunchers 
crunchers.installed # all names 
crunchers.cruncherA # actual module object, but you can't use it since you don't know the name when you write the code 
# turns out the be pretty much the same as the first solution :p 
mycruncher = getattr(crunchers, crunchers.installed[0]) 
+0

爲什麼繞過翻譯的進口邏輯是什麼? – 2009-11-03 17:39:01

+0

@ THC4k:我使用自定義函數導入的原因之一是我不知道我正在導入的模塊的名稱,我希望它以自己的名稱導入。 – 2009-11-03 17:42:25

+0

例如,如果你想在運行期間決定使用哪個模板引擎(mako /獵豹/ etc),你需要'__import__'。 – 2009-11-03 17:45:17

0

根據__import__的幫助:

__import__(name, globals={}, locals={}, fromlist=[], level=-1) -> module 

Import a module. The globals are only used to determine the context; 
they are not modified. ... 

所以你可以簡單地得到你的父框架的全局變量,並將其用於致電__import__

def import_something(s): 
    return __import__(s, sys._getframe(1).f_globals) 

注:前2.6,__import__的簽名不同,它根本就可選參數,而不是使用kwargs。由於globals是這兩種情況下的第二個參數,所以它被稱爲上面的方式工作正常。只是要注意,如果你決定使用任何其他論點。

+1

你仍然只是返回模塊,我認爲OP想要的東西比這更神奇。 (因爲否則你可以直接調用__import__,而不是包裝它)。 – 2009-11-03 17:45:28

1

您可以使用CPython中的父框架將模塊安裝到該框架的本地(僅限該框架)中。缺點是a)這真的很晦氣,而且b)sys._getframe()不能保證在其他python實現中存在。

def importer(): 
    f = sys._getframe(1) # Get the parent frame 
    f.f_locals["some_name"] = __import__(module_name, f.f_globals, f.f_locals) 

你還需要安裝模塊到f_locals,因爲進口實際上並不會爲你做的 - 你只是提供父框架當地人和全局的適當的範圍內。

然後在您的通話功能,你可以有:

def foo(): 
    importer() # Magically makes 'some_name' available to the calling function 
    some_name.some_func() 
1

您正在尋找這樣的事情?

def my_import(*names): 
    for name in names: 
     sys._getframe(1).f_locals[name] = __import__(name) 

那麼你可以這樣調用:

my_import("os", "re") 

namelist = ["os", "re"] 
my_import(*namelist) 
+0

'globals'會將它導入一級還是頂級?它應該只有一個級別,所以它的行爲就像是一個「import」語句。 – 2009-11-03 18:16:54

+0

你說得對,我相應地更改了代碼。那麼,看看其他解決方案,它現在看起來像詹姆斯和尼克剛纔發佈的那樣。 – RedGlyph 2009-11-03 18:51:23

+0

(How)我可以使用它來複制導入語句,如:「從模塊導入fun fun as F」和「import mod.submod as S」? – David 2015-01-28 17:55:21