在 Python 中获取调用函数模块的 __name__

2025-03-13 09:09:00
admin
原创
83
摘要:问题描述:假设myapp/foo.py包含:def info(msg): caller_name = ???? print '[%s] %s' % (caller_name, msg) 并myapp/bar.py包含:import foo foo.info('Hello') # => [...

问题描述:

假设myapp/foo.py包含:

def info(msg):
    caller_name = ????
    print '[%s] %s' % (caller_name, msg)

myapp/bar.py包含:

import foo
foo.info('Hello') # => [myapp.bar] Hello

在这种情况下,我希望caller_name将其设置为__name__调用函数模块(即“myapp.foo”)的属性。如何实现?


解决方案 1:

检查检查模块:

inspect.stack()将返回堆栈信息。

在函数内部,inspect.stack()[1]将返回调用者的堆栈。从那里,您可以获得有关调用者的函数名称、模块等的更多信息。

有关详细信息,请参阅文档:

http://docs.python.org/library/inspect.html

此外,Doug Hellmann 在他的 PyMOTW 系列中对检查模块进行了很好的描述:

http://pymotw.com/2/inspect/index.html#module-inspect

编辑:这里有一些可以完成你想要的代码,我认为:

import inspect 

def info(msg):
    frm = inspect.stack()[1]
    mod = inspect.getmodule(frm[0])
    print '[%s] %s' % (mod.__name__, msg)

解决方案 2:

面对类似的问题,我发现sys 模块中的sys._current_frames()包含有趣的信息,可以帮助您,而无需导入检查,至少在特定用例中是这样。

>>> sys._current_frames()
{4052: <frame object at 0x03200C98>}

然后您可以使用 f_back “向上移动”:

>>> f = sys._current_frames().values()[0]
>>> # for python3: f = list(sys._current_frames().values())[0]

>>> print f.f_back.f_globals['__file__']
'/base/data/home/apps/apricot/1.6456165165151/caller.py'

>>> print f.f_back.f_globals['__name__']
'__main__'

对于文件名,您还可以使用 f.f_back.f_code.co_filename,如上文 Mark Roddy 所建议的。我不确定此方法的限制和注意事项(多线程很可能是个问题),但我打算在我的案例中使用它。

解决方案 3:

我不建议这样做,但你可以用以下方法实现你的目标:

def caller_name():
    frame=inspect.currentframe()
    frame=frame.f_back.f_back
    code=frame.f_code
    return code.co_filename

然后按如下方式更新您现有的方法:

def info(msg):
    caller = caller_name()
    print '[%s] %s' % (caller, msg)

解决方案 4:

对于我来说,以下这句话就足以获得来电者的姓名。

import inspect
frame = inspect.stack()[-1]
print(frame.filename)

解决方案 5:

这是一个使用 的版本inspect,与上面的答案类似,但不是获取整个堆栈,而是只遍历我们感兴趣的帧(默认情况下是前 2 个),并处理可能发生的情况,None这样您就不会得到AttributeError结果,而是返回默认值。您还可以配置深度(如果深度为 1,则意味着返回直接调用者——相当于inspect.stack[1]——等等)。

import inspect

def caller_module_name(depth: int = 1, default: str | None = '__main__') -> str | None:
    frame = inspect.currentframe()
    if not frame:
        return default

    # Go back up the stack to the caller (or caller's caller, etc.)
    # (add 1 to depth to account for this function itself)
    for _ in range(depth + 1):
        if not (frame := frame.f_back):
            return default

    if module := inspect.getmodule(frame):
        return module.__name__

    return default

我不确定默认值的最佳选择是什么,"__main__"或者__name__只是None合适的。下面提到的打字模块中的内部函数使用硬编码字符串"__main__"作为默认值,所以我做了同样的事情,但默认值的意义可能取决于应用程序以及它应该在何处/如何运行。

看看它在 CPython 源代码中是如何内部完成的可能会很有趣,例如这里的 typing module。但是,这是使用内部 API 的,并且只能保证在 CPython 上工作,并且没有向后兼容的保证。因此,最好使用公共 API(在inspect模块中)编写它。(显然,它仍然无法在没有堆栈框架支持的 Python 解释器上运行,正如检查模块文档中警告的那样,但通过使用inspect模块和处理None,至少您不会遇到异常,并且仍然可以获得合理的返回值)。

解决方案 6:

调用inspect.getmodule()框架对象枚举中的模块对象,sys.modules并将框架对象对应的代码对象的文件路径与模块对象的文件路径(module.__file__针对每个模块)进行比较。

以下解决方案可避免此类开销。

import sys

def info(msg):
    caller_name = sys._getframe(1).f_globals['__name__']
    ...
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   4008  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2751  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   86  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   97  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   85  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用