【问题标题】:Finding the local name of a module from within that module从模块中查找模块的本地名称
【发布时间】:2012-01-11 21:35:17
【问题描述】:

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

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.install() 首次运行时,我必须知道myModule 的确切名称。如果用户使用import myModule as otherModule 导入模块,__name__ 不够具体。

如果有更好的方法来做到这一点,不涉及使用确切的模块名称,我很想知道。就像以某种方式将 myModule.run 的引用转换为我可以存储在 Maya 中并稍后解包的字符串。我一直在尝试使用inspect 模块来查找此信息,但我不断发现它不起作用的情况,我不得不回去再摆弄它一些。它也似乎有点乱。这是我现在正在使用的,如果从 __main__ 调用 myModule 将不起作用。

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 ...导入。

【问题讨论】:

    标签: python module namespaces


    【解决方案1】:

    唯一可行的方法是:

    import some.plugin as wanna_have
    
    wanna_have.install(globals(), "wanna_have")
    

    这是为什么呢?这里需要both导入模块和导入模块的命名空间,第一个需要你传递globals()。防止这种情况发生的唯一方法是在 install() 方法中向上一个堆栈帧,假设调用代码是具有别名的代码。当您使用签名install(importer=None, imported=__name__) 时,传递所有这些东西的需要可以减少到使用“as”或调用者不是一帧的情况。

    【讨论】:

    • 这不是“可以永远工作的唯一_方式” - python 有足够的自省来允许一些符合 OP 要求的内容。但是在这种情况下需要一个显式的 init 调用确实非常干净。
    【解决方案2】:

    一种接近您正在尝试的方法应该可行 - bt 它会很复杂,因为您可以验证。

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

    相当于

    import module
    othername = module
    del module
    

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

    而不是传递: guessedname.run()

    尝试通过:

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

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

    【讨论】:

    • 谢谢,这是一个比使用框架更好的解决方案!完美运行。
    【解决方案3】:

    我提出以下解决方案:

    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
    

    【讨论】:

    • 这无济于事 - 他不必在运行他的代码的模块中找到模块名称 - 他必须在导入他的模块的第三方编写的模块中找到它的名称
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-06
    • 2018-09-04
    • 2019-07-03
    • 2016-02-11
    • 1970-01-01
    相关资源
    最近更新 更多