检查Python对象的工具而不修改它们

12 投票
2 回答
1456 浏览
提问于 2025-04-16 17:29

今天晚上我在找一个Python程序中的资源泄露问题时,发现现代的ORM(对象关系映射)让这个工作变得相当困难。一个实际上在内存中孤零零的对象,开始检查它的属性时,突然就会显示出有十几个相关的对象。这是因为每次查看属性时,都会调用一个描述符,这个描述符会即时拉取更多的信息。

我甚至注意到,简单地用print打印一个特定的对象,竟然会触发数据库查询,把更多关联的对象加载到内存中——这搞坏了我之前计算的引用计数。因为这个对象的__repr__()方法是根据几个关联对象来构建显示名称的。

其实,有一些方法可以在不影响对象的情况下进行检查,比如type(obj)id(obj)obj.__dict__。不过,注意不要直接打印__dict__,因为那会对字典里的每一个值调用__repr__()有没有人把这些“安全”的检查方法结合起来,在像Python调试器这样的提示符下,方便地检查和探索Python对象图,以便我能看到这些文件是如何被打开的,导致我用完了文件描述符?

我基本上需要一个反海森堡工具,能够防止我的检查行为产生任何副作用!

“inspect”模块:

有一个答案建议我尝试inspect()模块,但看起来它会解引用你提供的对象的每一个属性:

import inspect
class Thing(object):
    @property
    def one(self):
        print 'one() got called!'
        return 1
t = Thing()
inspect.getmembers(t)

这会输出:

one() got called!
[('__class__', <class '__main__.Thing'>),
 ('__delattr__', <method-wrapper '__delattr__'…),
 …
 ('one', 1)]

2 个回答

0

我对各种方法有点摸不着头脑,不太清楚它们有多“安全”(这似乎跟你的具体情况有关系)。不过,inspect模块提供了很多很棒的检查工具。

5

Python 3.2 现在提供了一个叫做 inspect.getattr_static() 的功能,正好可以用在这种情况下:http://docs.python.org/py3k/library/inspect#fetching-attributes-statically

文档页面顶部的源代码链接应该能让你比较容易地将这个功能移植到早期版本(不过要记住,因为这是3.x版本的标准库代码,所以它不适合处理旧式类)。

不过,我不知道有没有现成的工具能够把这种技术和 obj.__dict__ 的检查结合起来,从而在不调用描述符的情况下,浏览整个对象图。

撰写回答