2012-11-12 47 views
2

我有一個字符串type,其值爲「MBSquareObject」。 MBSquareObject是名爲MBObject的文件中的類。我想動態導入MBSquareObject從字符串中用Python導入模塊

如果正方形物體在它自己的文件,這個工程:

__import__(type) 

不過,我想要做的是from MBObject import MBSquareObject等同。但是,這不起作用:

from MBObject __import__(type) 

我還能怎麼做?

編輯:給出的答案假定MBSquareObject是MBObject上的某種對象,但它只是另一個類。 MBSquareObject是MBObject的一個子類,因此它們被列在同一個文件中。

編輯:由於某種原因,沒有答案正在工作。下面是我有:

# this is imported at the top of the file 
from MBObject import MBObject 
type = 'MBSquareObject' 
__import__('MBObject', globals(), locals(), [type]) 
object_class = eval(type) 
object = object_class() 

錯誤:NameError:名字 'MBSquareObject' 沒有定義

回答

4

你舉的例子表明該模塊名稱MBObject不需要被動態訪問,只有內部的對象。在這種情況下,你可以做

import MBObject 
thing = getattr(MBObject, type) 

編輯:一個問題是,你是給你的模塊和類的名稱相同,因此很難區分它們在你的代碼。你在類和模塊之間感到困惑。你有兩個東西叫做MBObject。一個是模塊,另一個是該模塊內的類。當你做from MBObject import MBObject時,你需要導入這個類,但是不要引用這個模塊,這使得後續從同一個模塊中導入第二個類(MBSquartObject)變得很笨拙。

你可以得到你想要用我上面給的代碼的效果,但你必須from MBObject import MBObject ---當你這樣做,你不給自己的模塊的引用,只有類在該模塊中。相反,只需執行import MBObject,然後通過MBObject.MBObject訪問MBObject類。

如果您希望能夠引用同一模塊中的MBObject類和其他類,而不用模塊名稱作爲前綴,請爲該模塊指定一個不同的名稱。 Python風格指南建議在MixedCase中以小寫字母和類命名模塊。所以命名你的模塊mbobject.py。然後你可以這樣做:

import mbobject 
from mbobject import MBObject 
thing = getattr(mbobject, type) 

一般來說,在模塊和類中給Python命名並不是一個好主意。模塊和類是不同的東西,並給他們相同的名稱可能導致這樣的混亂,你不清楚你是否在處理模塊或類。

+0

等待對不起,我應該指定:MBSquareObject是一個類,MBObject的一個子類。他們只是放在同一個文件中。 – Snowman

+0

@mohabitar文件叫什麼?如果它被命名爲'MBObject.py',那麼這應該工作。在這種情況下,MBObject指的是模塊名稱,而不是類名稱。 –

+0

@mohabitar:在這種情況下,您需要編輯您的問題以更清楚地解釋您要做的事情。 '從MBObject導入MBSquareObject'將從一個名爲'MBObject'的*模塊導入一個東西(類,數字,字符串等等)。你知道你想要導入的模塊的名稱,還是必須動態確定,如果是這樣,如何? (也就是說,你是從模塊中單獨確定模塊還是以某種方式鏈接?) – BrenBarn

0

如何:

module = __import__('MSObject.' + 'MBSquareObject') 
3

__import__可以採用額外的參數指定應該導入哪些對象。從這個函數的返回中,你可以獲取你想要的任何對象。

source_module = 'MBObject' 
object_in_module = 'MBSquareObject' 

obj = getattr(__import__(source_module, globals(), locals(), [object_in_module]), 
       object_in_module) 
+0

這也不起作用。請參閱編輯 – Snowman

+0

'__import__'返回導入的模塊 - 您需要存儲該返回值,如示例中所示。導入不會自動添加到全局範圍(爲此,'從x導入y'將工作得很好)。 –

+0

所以我會用它來代替'object_class = eval(type)'? – Snowman

1

__import__功能的完整語法描述the documentation

__import__(name[, globals[, locals[, fromlist[, level]]]]) 

這裏fromlist是要從導入的模塊導入的項目列表。像

from module import object1, object2 

的聲明是作爲像

module = __import__('module', globals(), locals(), ['object1', 'object2']) 
object1 = getattr(module, 'object1') 
object2 = getattr(module, 'object2') 

所以你的情況,你可以使用

module = __import__('MBObject', globals(), locals(), [type]) 
the_object = getattr(module, type) 

在最新版本的Python,因爲3.1,有一個模塊importlib你可以用它來做到這一點。雖然我能找到的唯一方法是使用模塊的實現__import__,這與內置實現基本相同,所以我想你可能會使用內置實現。

+0

我試過這個,但它不工作。請參閱編輯 – Snowman

+0

不,這不是你試過的。或者至少你編輯成你的問題不是任何答案告訴你做的。在你說它不工作之前,嘗試使用我給你的代碼。 –

+0

這可能是此主題中最優雅的解決方案。 –