tags:

views:

106

answers:

2

In python 2.5, I have the following code in a module called 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()

However, when I run this, it prints out:

__main__

If I create a second file called modtest2.py and run it:

import modtest

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

This prints out:

modtest

How can I change the decorator to always print out modtest, the name of the module in which the class is defined?

A: 

I'm guessing you could use sys._getframe() hackery to get at what you want.

djc
Looking into that, I think the problem is that the method hasn't actually been called yet, so I'm not sure if there's any information in the frame stack that I can use.
Brent Newey
The decorator has been called from the class-scope, though, so I guess you can still do something there...
djc
sys._getframe().f_code.co_filename works to a point, but I still only have the file name of the module, not the full path.
Brent Newey
Use os.path.abspath() on it?
djc
+1  A: 

When you execute a python source file directly, the module name of that file is __main__, even if it is known by another name when you execute some other file and import it.

You probably want to do like you did in modtest2, and import the module containing the class definition instead of executing that file directly. However, you can get the filename of the main module like so, for your diagnostic purposes:

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
Matt Anderson
This is a good answer. Is it possible to get the full module path as is returned by self.__module__ rather than just the module file name?
Brent Newey
I'm not sure that you can do that accurately with any ease. You could approximate it by walking up the directory tree (starting with the directory of `__file__`) and looking for files named `__init__.py` in each, stopping when you don't find one, and then mashing the path segments together with dots. I would expect that this would differ from the true full module path in some cases.
Matt Anderson
This method could work, but for two python modules of unknown relation is it possible to obtain the directory of the file?
Brent Newey