我想用pyc来测试扩展。在
我测试的部分内容是对象的引用计数是否正确。因此,我用纯python构建了一个小测试,这让我很困惑。。。在
从Ipython我得到:
In [1]: x = 153513514215
In [2]: import sys
In [3]: sys.getrefcount(x)
Out[3]: 2
所以一切都很好,一个来自任务的参考,一个来自呼叫者。在
但是下面的脚本(stackoverflow_测试.py)给出了以下结果
^{pr2}$当我把它作为一个普通的python脚本运行时
$ python3 stackoverflow_test.py
x refcount = 4
y refcount = 4
为什么是4而不是2?。在
当我用pytest运行它时
$ python3 -m pytest stackoverflow_test.py
=================== test session starts ===================
platform linux -- Python 3.4.3, pytest-3.0.7, py-1.4.33, pluggy-0.4.0
rootdir: /opt/projects/0001_Intomics/00005_TextMining/jcr/textmining/tests, inifile:
collected 2 items
stackoverflow_test.py FF
======================== FAILURES =========================
___________________ test_ref_count_int ____________________
def test_ref_count_int():
x = 677461248192962146784178
> assert sys.getrefcount(x) == 2
E assert 3 == 2
E + where 3 = <built-in function getrefcount>(677461248192962146784178)
E + where <built-in function getrefcount> = sys.getrefcount
stackoverflow_test.py:7: AssertionError
___________________ test_ref_count_str ____________________
def test_ref_count_str():
y = 'very long and probbably very unique string'
> assert sys.getrefcount(y) == 2
E AssertionError: assert 3 == 2
E + where 3 = <built-in function getrefcount>('very long and probbably very unique string')
E + where <built-in function getrefcount> = sys.getrefcount
stackoverflow_test.py:11: AssertionError
为什么是3而不是2?在
问题:为什么会这样
我希望它在所有3种情况下都像ipython一样,有人能解释一下发生了什么,并给我一些提示,如何最好地测试我正在创建的对象。在
代码中的文字存储在代码对象中。字节码堆栈是另一个引用:
LOAD_CONST
操作码从附加到代码对象的co_consts
元组加载对象;该元组是一个引用。STORE_FAST
然后将其放入局部变量中,这是第二个引用。在然后是
LOAD_FAST
操作码,它从本地存储中取一个名称并将其放入堆栈again incrementing the reference count。在最后但并非最不重要的是,将该值传递给
sys.getrefcount()
调用。在如果您想了解引用对象的内容,可以查看^{} ;此函数在调用时排除自身和堆栈,因此您可以在心里添加+2:
^{pr2}$它打印两个对象,
co_consts
元组和当前调用帧(对于局部变量)。在py.test
执行一些额外的import-time magic,这rewrites ^{您可能还想阅读扩展的python的C或C++ +eEM>文档,c++ API手册的Objects, Types and Reference Counts section,最后但不是最不相同的Debugging Builds section,来学习如何创建一个Python构建,帮助您详细地跟踪引用计数。在
你不应该依赖于对一个对象的特定数量的引用。我可以通过访问function对象简单地添加对对象的更多引用,例如(
foo = normal_te_st.__code__.co_conts[1]
甚至在运行函数之前都会增加引用计数)。真正需要增加引用计数的是一个实现细节。只需确保您自己的代码正确处理引用即可。在相关问题 更多 >
编程相关推荐