繁体   English   中英

如何访问导入模块的名称?

[英]How can I access the name a module was imported as?

我想在我的Python模块foo编写一个简单的教程。

如果模块作为foo导入,我希望本教程将其称为foo

>>> import foo
>>> foo.tutorial()
Please run foo.baz().

但是,当模块导入为bar ,我希望本教程将其称为bar

>>> import foo as bar
>>> bar.tutorial()
Please run bar.baz().

我知道__name____package__变量都不会在import ... as ...上更改其值。

与众不同是否可以在python中检测模块的导入方式? -知道导入模块的第一个别名就足够了。

它不是很漂亮,万无一失,也不值得制作,但是:

import inspect
import sys


thismod = sys.modules[__name__]


def imported_as():
    imported_frame = inspect.currentframe().f_back.f_back
    for k, v in imported_frame.f_locals.items():
        if v is thismod:
            return k
    for k, v in imported_frame.f_globals.items():
        if v is thismod:
            return k


def tutorial():
    print('please call {}.baz()'.format(imported_as()))

一个小小的解释:

  • 跳两个堆栈帧
  • 查看局部变量和全局变量以查找与模块相同的模块对象

为什么您真的不应该这样做:

  • 这不是万无一失的:
    • from进口将打破这一点
    • 同一模块的多个导入将不确定地仅给出第一个找到的名称
  • inspect.currentframe超级神奇,通常应在生产代码中避免使用

这是与安东尼类似的解决方案。 我相信它可以更好地处理多种进口。 from进口仍然是一个问题。

import inspect
import re
import readline

def tutorial():
    frame = inspect.currentframe().f_back    
    if "__file__" in frame.f_locals:
        f = inspect.getframeinfo(frame)
        m = re.search(r"(([^\.]*).*)\.tutorial", f.code_context[0].strip())
        if m:
            parent,path = m.group(2),m.group(1)
            if inspect.ismodule(frame.f_locals[parent]):
                print "Please run {}.baz()".format(path)
                return
        print "Verify import and run foo.baz()"
    else:
        loc = frame.f_locals
        glo = frame.f_globals
        local_foo = [(k, v.__name__)for k,v in loc.items() if inspect.ismodule(v) and v.__name__=="foo"]
        global_foo = [(k, v.__name__)for k,v in glo.items() if inspect.ismodule(v) and v.__name__=="foo"]
        if local_foo and set(local_foo)==set(global_foo):
            print "Please run {}.baz()".format(global_foo[-1][0])
        elif local_foo and global_foo:
            print "Please run {}.baz() in local scope or {}.baz()".format(local_foo[-1][0], global_foo[-1][0])
        elif local_foo:
            print "Please run {}.baz() in local scope".format(local_foo[-1][0])
        elif global_foo:
            print "Please run {}.baz()".format(global_foo[-1][0])
        else:
            n = readline.get_current_history_length()
            h = [str(readline.get_history_item(i)) for i in range(n)] + [readline.get_line_buffer()]
            h.reverse()
            for i in h:
                matches = re.findall(r"([A-Za-z0-9_-]*(\.[A-Za-z0-9_-]*)*)\.tutorial", i)
                for match in matches:
                    if _baz_check(glo, match[0]):
                        print "Please run {}.baz()".format(match[0])
                        return
            print "Verify import and run foo.baz()"


def _baz_check(d, path):
    path = path.split(".")
    if path[0] not in d:
        return False
    cur = d[path[0]]
    for i in range(1,len(path)):
        if not hasattr(cur, path[i]):
            return False
        cur = getattr(cur, path[i])
    return hasattr(cur, "__name__") and cur.__name__ == "foo" and hasattr(cur, "baz")

def baz():
    print "Baz"
import foo
foo.tutorial()
import foo as bar
bar.tutorial()

def f():
    import foo as local_foo
    local_foo.tutorial()

f()
from foo import tutorial
tutorial()
import mod
mod.foo.tutorial()
from mod import foo as dum
dum.tutorial()
Please run foo.baz()
Please run bar.baz()
Please run local_foo.baz()
Verify import and run foo.baz()
Please run mod.foo.baz()
Please run dum.baz()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM