2010-02-17 108 views
13

在Python 2.5中,我有一个模块在下面的代码名为modtest.py:如何获取对象类定义的模块名称而不是对象实例化的模块名称?

def print_method_module(method): 
    def printer(self): 
     print self.__module__ 
     return method(self) 
    return printer 

class ModTest(): 

    @print_method_module 
    def testmethod(self): 
     pass 

if __name__ == "__main__": 
    ModTest().testmethod() 

然而,当我运行它,它打印出:

__main__ 

如果我创建第二个文件所谓modtest2.py并运行它:

import modtest 

if __name__ == "__main__": 
    modtest.ModTest().testmethod() 

此打印出:

modtest 

如何更改装饰器,始终打印出modtest,该类定义的模块的名称?

回答

9

当您直接执行python源文件时,该文件的模块名称为__main__,即使您在执行某个其他文件并将其导入时被另一个名称所知。

您可能想要像在modtest2中那样做,然后导入包含类定义的模块,而不是直接执行该文件。但是,为了您的诊断目的,您可以获取主模块的文件名,如下所示:

def print_method_module(method): 
    def printer(self): 
     name = self.__module__ 
     if name == '__main__': 
      filename = sys.modules[self.__module__].__file__ 
      name = os.path.splitext(os.path.basename(filename))[0] 
     print name 
     return method(self) 
    return printer 
+0

这是一个很好的答案。是否有可能得到完整的模块路径,就像self.__ module__返回的那样,而不仅仅是模块文件名? –

+0

我不确定您是否可以轻松地做到这一点。你可以通过在目录树上行走(从'__file__'开始)并寻找名为'__init __。py'的文件,当你没有找到文件时停下来,然后将路径段与点。我希望这在某些情况下会与真正的完整模块路径不同。 –

+0

这种方法可以工作,但对于未知关系的两个python模块是否可以获取文件的目录? –

-1

我猜你可以使用sys._getframe()hackery来得到你想要的。

+0

调查一下,我认为问题在于该方法尚未实际调用,所以我没有确定是否有任何可以使用的帧堆栈中的信息。 –

+0

尽管从类范围调用了装饰器,所以我想你仍然可以在那里做些什么...... – djc

+0

sys._getframe()。f_code.co_filename工作到一个点,但我仍然只有文件名该模块,而不是完整的路径。 –