2010-01-08 118 views
2

我正在編寫一段可重複使用的代碼來導入我需要的地方,但它需要一些關於導入模塊的信息。我有一個解決方法,可以做我想做的事,但它有點難看。有沒有更好的辦法?Python:從導入的模塊中獲取導入模塊的詳細信息

這是我正在做的簡化版本。

我想要什麼:導入一個方法並使用它,但看看mod2中的f。它需要來自導入模塊的一些信息。

MOD1:

from mod2 import f 
f(...) 

MOD2:

from things_i_want import parent_module, importing_module 
def f(*args, **kwargs): 
    from importing_module.parent_module import models 
    # ... do some stuff with it, including populating v with a string 

    v = 'some_string' 
    m = getattr(importing_module, v, None) 
    if callable(m) 
     return m(*args, **kwargs) 

我的醜的解決方法:

MOD1:

from mod2 import f as _f 
def f(*a, **k):return _f(__name__, globals(), *a, **k) 
f(...) 

模2:

def f(module_name, globs, *args, **kwargs): 
    # find parent modules path 
    parent_module_path = module_name.split('.')[0:-1] 
    # find models modules path 
    models_path = parent_module_path + ['models',] 
    # import it 
    models = __import__('.'.join(models_path), {}, {}, ['']) 
    # ... do some stuff with it, including populating v with a string 

    v = 'some_string' 
    if v in globs: 
     return globs[v](*args, **kwargs) 
+1

如果你給我們一個關於*爲什麼*你想要這個的小背景可能會有幫助,因爲這是一個非常不尋常的要求。 – 2010-01-08 10:11:33

+2

這是充滿危險的。導入的模塊不應該通過神奇的方式「意識到」它們的上下文。這是一場測試噩夢。你想跟隨所謂的「依賴注入」,你明確告訴導入的模塊它需要知道什麼。上下文沒有神奇的「發現」。 – 2010-01-08 11:29:04

+0

給出一些上下文: 這是在Django的webapp中。我在我的urlconf中調用了一個方法,它將RESTful URL全部映射到模型視圖中的方法。此方法查看request.method,然後檢查foo_delete等視圖中是否存在方法並調用它,或者爲該url和請求方法運行默認操作。 – Jake 2010-01-11 01:07:42

回答

4

這是一個壞主意,因爲模塊被緩存。

因此,如果另一個模塊,比如mod3.py,也導入mod2,它將首次得到相同的對象。該模塊不會重新導入。

也許你自己導入mod2之前導入了一些其他模塊,然後你就不再是導入mod2的那個模塊了。模塊只能導入一次。

因此,不要試圖獲取誰導入模塊,您應該使用另一種可重用的方法。也許使用類並傳遞實例?

+0

所以我醜陋的解決方法可能不是那麼難看? 請參閱上面的註釋以瞭解上下文。 – Jake 2010-01-11 01:03:50

+0

這是醜陋的,因爲它試圖隱藏它的意圖。明示比隱含更好。你爲什麼不把類傳給f(),它裏面包含了delete/insert/update/select方法?此外,Django在任何地方都使用字符串'project.app.myfun'來引用函數,所以django中的某個函數接受一個字符串並返回它所引用的實際函數對象。爲什麼不使用它? – nosklo 2010-01-11 10:26:16

+0

好點。有一個函數(get_app)需要一個像「project.app」這樣的字符串並返回它,可能會有一個更深一層。或者我可以使用__import__? 我寧願不把它們包裝在一個類中,因爲我希望它們保留在視圖文件中,以便其他URL可以指向它們,並且儘可能少地改變Django。 – Jake 2010-01-12 01:09:59