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



我在给定的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

singleton装饰器根据http://www.python.org/dev/peps/pep-0318/#examples

实例创建python文件:'/Users/mysel/code/Instance_creation_python\ufile.py':

from myobjectmodule import MyObject
A = MyObject('Foo')

第三个python文件:'/Users/mysel/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.引擎为所有应用程序提供功能,但对于某些功能,需要知道哪些对象源自哪个应用程序/文件。

在不讨论为什么要这样做的优点的情况下,这里有一种方法:

# 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"

所有关于这只是调试的好主意的注意事项,除了此之外,您还可以使用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

这个答案略有不同,因为它不使用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

最新更新