如何知道在Python中实例化对象的位置?

时间:2014-03-03 12:38:47

标签: python python-2.7

我在给定的python模块中定义了一个类。从其他一些python文件中,我将创建所述类的实例。实例在单个注册表对象中的对象创建时注册,即在__init__()期间。从第三种类型的python文件我想访问注册表,查看其中的对象,并能够找出这些对象事先创建的文件。

代码示例可能如下所示:

Python模块文件:'/ Users / myself / code / myobjectmodule.py':

@singleton
class Registry(object):
     def __init__(self):
         self.objects = {}

class MyObject(object):
    def __init__(self, object_name):
        self.object_name = object_name
        Registry().objects[self.object_name] = self
根据{{​​3}}

singleton装饰者

实例创建python文件:'/ Users / myself / code/instance_creation_python_file.py':

from myobjectmodule import MyObject

A = MyObject('Foo')

第三个python文件:'/ Users / myself / code/registry_access.py':

from myobjectmodule import Registry

registry = Registry()
foo = registry.objects['Foo']

现在,我希望有一个方法foo.get_file_of_object_creation()

如何实施此方法?

编辑:

这种方法的原因如下:
1.框架定义了一组对象,这些对象应指定数据源并在加载后包含数据(MyObject) 2.使用此框架的应用程序应指定这些对象并使用它们。每个应用程序都保存在.py文件或文件夹中,该文件夹还通过其名称指定应用程序的名称 3.引擎为所有应用程序提供功能,但对于某些功能,需要知道哪些对象来自哪个应用程序/文件。

3 个答案:

答案 0 :(得分:4)

如果不想了解为什么要这样做的优点,可以采用以下方法:

# assume the file is saved as "temp.py"

import inspect

class RegisteredObject(object):
    def __new__(cls, *args, **kwargs):
        new_instance = super(RegisteredObject, cls).__new__(cls, *args, **kwargs)
        stack_trace = inspect.stack()
        created_at = '%s:%d' % (
            stack_trace[1][1], stack_trace[1][2])
        new_instance.created_at = created_at 
        return new_instance

    def get_file_of_object_creation(self):
        return self.created_at

class MyObject(RegisteredObject):
    pass

def create_A():
    return MyObject()

def create_B():
    return MyObject()

if __name__ == '__main__':
    t1 = create_A()
    t2 = create_B()
    t3 = create_A()
    t4 = create_B()
    t5 = MyObject()
    print '"t1" was created at "%s"' % t1.get_file_of_object_creation()
    print '"t2" was created at "%s"' % t2.get_file_of_object_creation()
    print '"t3" was created at "%s"' % t3.get_file_of_object_creation()
    print '"t4" was created at "%s"' % t4.get_file_of_object_creation()
    print '"t5" was created at "%s"' % t5.get_file_of_object_creation()

输出:

$ python temp.py
"t1" was created at "temp.py:19"
"t2" was created at "temp.py:22"
"t3" was created at "temp.py:19"
"t4" was created at "temp.py:22"
"t5" was created at "temp.py:29"

答案 1 :(得分:3)

关于这一点的所有警告只是调试的好主意,你可以使用inspect模块。

import inspect

def get_caller():
    return inspect.stack()[2]   # 1 is get_caller's caller

def trace_call():
    _, filename, line, function, _, _ = get_caller()
    print("Called by %r at %r:%d" % (function, filename, line))

def main():
    trace_call()

main()

产生

Called by 'main' at 'trace.py':11

答案 2 :(得分:0)

这个答案略有不同,因为它没有使用inspect.stack,因为我发现它在Python 3中特别慢。

import inspect


class Locatable:

    def __new__(cls, *_args, **_kwargs):
        # Background: http://eli.thegreenplace.net/2012/04/16/python-object-creation-sequence
        obj = super().__new__(cls)
        obj.location = obj._initialization_location()  # pylint: disable=protected-access
        return obj

    @staticmethod
    def _initialization_location():
        # Background: https://stackoverflow.com/a/42653524/
        frame = inspect.currentframe()
        while frame:
            if frame.f_code.co_name == '<module>':
                return {'module': frame.f_globals['__name__'], 'line': frame.f_lineno}
            frame = frame.f_back

    @property
    def name(self):
        module_name = self.__module__
        class_name = self.__class__.__qualname__  # pylint: disable=no-member
        return module_name + '.' + class_name

以上是可以继承的基类。

location属性应该包含实例化类的模块的名称,例如mypackage.mymodule