How can I access the current executing module or class name in Python?
我希望能够动态地从导入的模块中检索当前正在执行的模块或类名。下面是一些代码:
PY.PY:
1 2 | def f(): print __name__ |
bar.py:
1 2 3 | from foo import f def b(): f() |
这显然不起作用,因为
编辑:
编辑:这是我使用这个的方法。我有两个不同的django应用程序,它们都需要将错误记录到文件中。假设它们被称为"appone"和"apptwo"。我还有一个地方可以记录这些文件:"
为了做到这一点,我认为最好的方法是让logger模块能够访问某种表示当前应用程序名称的全局变量,因为它负责知道父日志目录的位置,并创建应用程序的日志目录(如果还不存在的话)。
从评论中——而不是问题中。
I am simply curious to see if what I am trying to do is possible.
"有可能"的答案总是"是"。总是。除非你的问题涉及到时间旅行、反重力或永久运动。
因为答案总是"是",所以你的问题是不正确的。真正的问题是"什么是让我的日志模块知道客户机名称的好方法?"或者类似的。
答案是"接受它作为一个参数",不要乱检查或寻找神秘的全局或其他技巧。
只需遵循logging.getlogger()的设计模式并使用显式命名的记录器。一个常见的成语是
1 | logger= logging.getLogger( __name__ ) |
它可以完美地处理几乎所有的日志命名。
这应该适用于引用当前模块:
1 2 | import sys sys.modules[__name__] |
"当前正在执行的模块"显然是foo,因为它包含当前正在运行的函数——我认为对于您想要的是foo的直接调用方的模块(如果您从foo中的函数调用f(),那么它本身可能是foo)。你想走多远取决于你想做什么。
在任何情况下,假设您需要立即调用方,您可以通过遍历调用堆栈来获得这一点。这可以通过调用
1 2 3 | def f(): caller = sys._getframe(1) # Obtain calling frame print"Called from module", caller.f_globals['__name__'] |
[编辑]:实际上,按照上面的建议使用inspect模块可能是获得堆栈帧的一种更干净的方法。等效代码为:
1 2 3 | def f(): caller = inspect.currentframe().f_back print"Called from module", caller.f_globals['__name__'] |
(系统框架记录为供内部使用-检查模块是一个更可靠的API)
我认为您希望使用inspect模块来检查python运行时堆栈。看看这个教程。我认为它提供了一个你想要做什么的几乎精确的例子。
要在另一个模块中获取对"主"模块的引用,请执行以下操作:
1 2 | import sys sys.modules['__main__'] |
然后获取模块的文件路径,其中包括其名称:
1 | sys.modules['__main__'].__file__ |
如果在"主"模块中,只需使用:
仅从文件路径获取文件名:
1 2 | import os os.path.basename(file_path) |
要将文件名与其扩展名分开,请执行以下操作:
1 | file_name.split(".")[0] |
要获取类实例的名称,请执行以下操作:
1 | instance.__class__.__name__ |
要获取类的名称:
1 | class.__name__ |
单独使用
对于文件名,只使用
完整路径使用
演示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /tmp $ cat f.py from pprint import pprint import os import sys pprint({ 'sys.modules[__name__]': sys.modules[__name__], '__file__': __file__, '__file__.split(os.path.sep)[-1]': __file__.split(os.path.sep)[-1], 'os.path.abspath(__file__)': os.path.abspath(__file__), }) /tmp $ cat i.py import f |
结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | ## on *Nix ## /tmp $ python3 f.py {'sys.modules[__name__]': <module '__main__' from 'f.py'>, '__file__': 'f.py', '__file__.split(os.path.sep)[-1]': 'f.py', 'os.path.abspath(__file__)': '/tmp/f.py'} /tmp $ python3 i.py {'sys.modules[__name__]': <module 'f' from '/tmp/f.pyc'>, '__file__': '/tmp/f.pyc', '__file__.split(os.path.sep)[-1]': 'f.pyc', 'os.path.abspath(__file__)': '/tmp/f.pyc'} ## on Windows ## PS C:\tmp> python3.exe f.py {'sys.modules[__name__]': <module '__main__' from 'f.py'>, '__file__': 'f.py', '__file__.split(os.path.sep)[-1]': 'f.py', 'os.path.abspath(__file__)': 'C:\\tools\\cygwin\\tmp\\f.py'} PS C:\tmp> python3.exe i.py {'sys.modules[__name__]': <module 'f' from 'C:\\tools\\cygwin\\tmp\\f.py'>, '__file__': 'C:\\tools\\cygwin\\tmp\\f.py', '__file__.split(os.path.sep)[-1]': 'f.py', 'os.path.abspath(__file__)': 'C:\\tools\\cygwin\\tmp\\f.py'} |
如果你想从末尾去掉".py",你可以很容易地做到。(但不要忘记,您可以运行一个".pyc")。
我认为这是不可能的,因为这超出了
我已经有一段时间没有做过python了,但我相信您可以通过它的回溯来访问调用者的全局和局部变量。
如果只需要文件名:
1 | file_name = __file__.split("/")[len(__file__.split("/"))-1] |
要获取包含文件夹的当前文件模块,以下是对我有效的:
1 2 3 | import os parts = os.path.splitext(__name__) module_name = parts[len(parts) - 2] |