2010-01-08 79 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