从该模块中查找模块的本地名称

时间:2012-01-11 21:35:18

标签: python module namespaces

我正在尝试从该模块内部获取模块导入的确切模块名称。像这样:

def install():
    print 'Local module name is %s' % __localModuleName__

我跑的时候:

import myModule as mm
mm.install()

会打印

Local module name is mm

我正在尝试制作的脚本将自己安装到外部应用程序Maya中。 Maya在python中根据需要评估我传递的字符串。现在,我正在尝试给Maya字符串"myModule.run()"。在这种情况下,首次运行myModule时,我必须知道myModule.install()的确切名称。如果用户使用__name__导入模块,则import myModule as otherModule不够具体。

如果有更好的方法来执行此操作而不涉及使用确切的模块名称,我很乐意知道。就像以某种方式将myModule.run的引用转换为字符串一样,我可以将其存储在Maya中,然后解压缩。我一直在尝试使用inspect模块来查找这些信息,但我一直在寻找不起作用的情况,我不得不再回过头来进行操作。它似乎也有点混乱。这就是我现在正在使用的内容,如果从myModule调用__main__,则无效。

MODULENAME = None
fr = inspect.currentframe()
try:
    while fr and not MODULENAME:
        if fr.f_globals:
            for name, obj in fr.f_globals.iteritems():
                if hasattr(obj, '__file__') and inspect.ismodule(obj) and obj.__file__ == __file__:
                    MODULENAME = name
        fr = fr.f_back
except:
    pass
finally:
    del fr

如果没有好的解决方案,我打算删除上述内容,并告诉用户使用import myModule as ...无法导入我的模块。

3 个答案:

答案 0 :(得分:1)

这种方法可行的唯一方法就是:

import some.plugin as wanna_have

wanna_have.install(globals(), "wanna_have")

为什么?您需要两者导入模块的命名空间和导入的模块,第一个要求您传递globals()。防止这种情况的唯一方法是在install()方法中 up 一个堆栈帧,假设调用代码具有别名。当您使用签名install(importer=None, imported=__name__)时,需要传递所有内容可以简化为使用“as”时的情况,或者调用者不是一个帧。

答案 1 :(得分:0)

我提出以下解决方案:

print 'Local module name is %s'%[key for key in vars() if 'myModule' in str(vars()[key])][0]

[0] - 这是为了防止您的模块以不同的名称多次导入,而您只需拿起第一个。如果您的模块未导入,则会出现“IndexError:list index out of range”,我认为您可以自行处理。

我用

尝试了
import numpy as np

然后我应用了上面提到的oneliner:

print 'Local module name is %s',[key for key in vars() if 'numpy' in str(vars()[key])][0]

得到结果:

Local module name is np

答案 2 :(得分:0)

接近你正在尝试的方法应该有效 - 但是你可以验证它会被卷入。

此外,“import module as othername”语法只是将模块对象双向绑定到另一个变量的方便方法。

它只相当于

import module
othername = module
del module

你的代码不应该依赖于它来运行。 但是,在全局sys.modules字典中,您的模块始终显示其“真实”名称。因此,如果您可以将字符串中的表达式传递给宿主应用程序,则应该尝试访问该字典中的模块 - 更不用说复杂了。

而不是传递: guessedname.run()

尝试传递:

__import__("sys").modules["<module_name>"].run()

并不关心在运行代码中引用模块的变量名称。 (这甚至允许用户为您的代码执行from module import *