2009-03-02 95 views
22

我希望能够从导入的模块中动态检索当前正在执行的模块或类名。下面是一些代码:如何在Python中访问当前正在执行的模块或类名?

foo.py:

def f(): 
    print __name__ 

bar.py:

from foo import f 

def b(): f() 

这显然不为__name__工作是包含模块的名称功能。我想在foo模块内部访问的是当前使用foo的执行模块的名称。所以在上面的情况下,它将是bar,但是如果有任何其他模块导入foo,我希望foo动态访问该模块的名称。

编辑:inspect模块看起来很有前途,但它不是我正在寻找。我所希望的是我可以访问的某种全局或环境级别的变量,它包含当前执行模块的名称。并不是说我不愿意遍历堆栈来查找这些信息 - 我只是认为Python可能已经公开了这些数据。

编辑:这是我如何使用这个。我有两个不同的Django应用程序,都需要将错误记录到文件。可以说他们被称为“AppOne”和“AppTwo”。我也有一个我想要登录这些文件的地方:“/home/hare/app_logs”。在任何给定点的每个应用程序中,我希望能够导入我的记录器模块并调用将日志字符串写入文件的日志函数。但是我想要做的是创建一个名为app_logs的目录,它是当前应用程序的名称(“AppOne”或“AppTwo”),以便每个应用程序的日志文件将放入其各自的日志目录中。

为了做到这一点,我认为最好的方式是记录器模块有权访问某种表示当前应用程序名称的全局变量,因为它负责知道父记录目录的位置,如果应用程序的日志目录尚不存在,则创建它。

+0

你为什么要打破这样的责任分配? – 2009-03-02 16:06:28

+1

我在一个日志记录模块中使用它 - 我想能够告诉哪个外部模块正在尝试记录,而无需调用者传递某种密钥。 – 2009-03-02 16:10:25

+0

您是否正在寻找启动程序执行的模块(即:__name__ =='__main__'的模块?或者直接称为foo.f()的模块,每次foo.f()都可能不同所谓的“ – 2009-03-02 16:18:39

回答

40

从评论 - 而不是问题。

我只是好奇,看看我正在尝试做什么是可能的。

“是否可能”的答案始终为“是”。总是。除非你的问题涉及时间旅行,反重力或永久运动。

由于答案总是“是”,所以你的问题是不合格的。真正的问题是“什么是让我的日志记录模块知道客户端名称的好方法?”或类似的东西。

答案是“接受它作为参数”。不要乱用检查或寻找神秘的全局或其他技巧。

只需遵循logging.getLogger()的设计模式并使用显式指定的记录器即可。一个常见的用法如下

logger= logging.getLogger(__name__) 

这几乎可以处理所有的日志命名。

3

我不认为这是可能的,因为这是foo的范围。 foo只会意识到它的内部范围,因为它可能被无数其他模块和应用程序所调用。

11

我想你想用的是inspect模块,来检查python运行时栈。看看这个tutorial。我认为它提供了一个你想要做的几乎确切的例子。

15

“当前正在执行的模块”显然是foo,因为它包含了当前正在运行的函数 - 我认为你想要的是foo的直接调用者模块的更好的描述(如果你是在foo中调用函数foo中的af()函数调用foo中的函数,你想上涨的距离取决于你想要的这个值

在任何情况下,假设你想要直接调用者,你可以获得这个可以通过调用sys._getframe来完成调用堆栈,可以通过适当数量的级别来执行。

def f(): 
    caller = sys._getframe(1) # Obtain calling frame 
    print "Called from module", caller.f_globals['__name__'] 

[编辑]:实际上,使用如上述的建议inspect模块可能是获得所述栈帧的更清洁的方式。等效代码:

def f(): 
    caller = inspect.currentframe().f_back 
    print "Called from module", caller.f_globals['__name__'] 

(sys._getframe被记录为供内部使用 - 在检查模块是一个更可靠的API)

1

这已经有一段时间,因为我做了蟒蛇,但我相信你可以通过其traceback访问调用者的全局和当地人。

7

__file__是调用当前模块的路径。

24

这应该引用当前模块的工作:

import sys 
sys.modules[__name__] 
1

要获得一个参考“__main__”模块时,在另一:

import sys 
sys.modules['__main__'] 

然后,为了获得模块的文件路径,包括其名称:

sys.modules['__main__'].__file__ 

如果在“__main__”模块中,只需使用: __file__

从文件路径获取是文件名:

import os 
os.path.basename(file_path) 

从它的扩展分开的文件名:

file_name.split(".")[0] 

为了获得一个类的实例的名称:

instance.__class__.__name__ 

要获得一个类的名称:

class.__name__ 
2

单独使用__file__会为您提供主模块的相对路径和导入模块的绝对路径。意识到这一点,我们可以通过我们的os.path工具的一些帮助,不断获得模块文件。

对于文件名只能使用__file__.split(os.path.sep)[-1]

如需完整路径使用os.path.abspath(__file__)

演示:

​​3210

结果:

## 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文件”来代替。)

1

如果你想要的文件的唯一名称:

file_name = __file__.split("/")[len(__file__.split("/"))-1] 
相关问题