2

나는 c- 확장명을 작성하고 pytest에서 테스트하고 싶다.파이썬 참조 카운트 c- 확장을 디버그하기 위해 계산

내가 테스트중인 부분은 참조 수가 내 개체에서 올바른지 여부입니다.

In [1]: x = 153513514215 

In [2]: import sys 

In [3]: sys.getrefcount(x) 
Out[3]: 2 

그래서 호출자에서 너무 좋아, 한 할당에서 참조 및 1 운임 : 그래서 나는 나 퍼즐 순수 파이썬의 작은 테스트 ... Ipython에서

내가 얻을 구축 할 수 있습니다. 나는 정상적인 파이썬 스크립트

$ python3 stackoverflow_test.py 
x refcount = 4 
y refcount = 4 

왜 4가 아닌 2로 실행할 때 다음 스크립트 (stackoverflow_test.py는) 다음과 같은 결과

import sys 

def test_ref_count_int(): 
    x = 677461248192962146784178 
    assert sys.getrefcount(x) == 2 

def test_ref_count_str(): 
    y = 'very long and probbably very unique string' 
    assert sys.getrefcount(y) == 2 

def normal_te_st(): 
    x = 222677461248192962146784178 
    y = '!!!!very long and probbably unique string!!!!' 
    print ('x refcount = {}'.format(sys.getrefcount(x))) 
    print ('y refcount = {}'.format(sys.getrefcount(y))) 

if __name__ == '__main__': 
    normal_te_st() 

을 제공하지만

?

내가

$ 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 pytest

으로 실행?

질문 : 그

  • 파이썬 = 4 심판 오는 방법
  • pytest = 3 심판
  • ipython 세션 = 2 심판 I가 그것을 기대

카운트 카운트 카운트 모든 3 가지 경우에 ipython에서와 같이 작동합니다. 아무도 무슨 일이 일어나는지 설명하고, 내가 만드는 객체를 테스트하는 방법을 알려줍니다.

답변

4

코드의 리터럴은 코드 개체에 저장됩니다. 바이트 코드 스택은 또 다른 기준이다

>>> import dis 
>>> def normal_te_st(): 
...  x = 222677461248192962146784178 
...  y = '!!!!very long and probbably unique string!!!!' 
...  print ('x refcount = {}'.format(sys.getrefcount(x))) 
...  print ('y refcount = {}'.format(sys.getrefcount(y))) 
... 
>>> normal_te_st.__code__.co_consts 
(None, 222677461248192962146784178, '!!!!very long and probbably unique string!!!!', 'x refcount = {}', 'y refcount = {}') 
>>> dis.dis(normal_te_st) 
    2   0 LOAD_CONST    1 (222677461248192962146784178) 
       2 STORE_FAST    0 (x) 

    3   4 LOAD_CONST    2 ('!!!!very long and probbably unique string!!!!') 
       6 STORE_FAST    1 (y) 

    4   8 LOAD_GLOBAL    0 (print) 
      10 LOAD_CONST    3 ('x refcount = {}') 
      12 LOAD_ATTR    1 (format) 
      14 LOAD_GLOBAL    2 (sys) 
      16 LOAD_ATTR    3 (getrefcount) 
      18 LOAD_FAST    0 (x) 
      20 CALL_FUNCTION   1 
      22 CALL_FUNCTION   1 
      24 CALL_FUNCTION   1 
      26 POP_TOP 

    5   28 LOAD_GLOBAL    0 (print) 
      30 LOAD_CONST    4 ('y refcount = {}') 
      32 LOAD_ATTR    1 (format) 
      34 LOAD_GLOBAL    2 (sys) 
      36 LOAD_ATTR    3 (getrefcount) 
      38 LOAD_FAST    1 (y) 
      40 CALL_FUNCTION   1 
      42 CALL_FUNCTION   1 
      44 CALL_FUNCTION   1 
      46 POP_TOP 
      48 LOAD_CONST    0 (None) 
      50 RETURN_VALUE 

LOAD_CONST

연산 코드는 코드 오브젝트에 첨부 co_consts 튜플에서 오브젝트를로드; 그 튜플은 하나의 참조입니다. STORE_FAST 그 다음에 두 번째 참조 인 로컬 변수에 넣습니다.

opcode가 LOAD_FAST인데 로컬 저장소의 이름을 사용하여 스택에 넣습니다 (again incrementing the reference count).

마지막으로,이 값을 sys.getrefcount() 호출에 전달합니다.

개체를 참조하는 방법에 대해 알아 보려면 gc.get_referrers()을 참조하십시오. 전화했을 때이 기능은 자체 스택을 제외, 그래서 당신은 정신적 +2를 추가 할 수 있습니다

2 개체를 인쇄
>>> import gc 
>>> def gc_demo(): 
...  x = 222677461248192962146784178 
...  print(gc.get_referrers(x)) 
... 
>>> gc_demo() 
[(None, 222677461248192962146784178), <frame object at 0x106a25a98>] 

; co_consts 튜플 및 현재 호출 프레임 (현지인 용).

py.test 일부 추가 import-time magicrewrites assert statements이며, 그 결과 참조 횟수가 다시 달라집니다.

또한 C 또는 C++ 문서와 파이썬을 늘이기 Reference Counts sectionC API 참조 설명서, 그리고 마지막으로 같은 같은 아니 적어도 Debugging Builds sectionObjects, Types and Reference Counts section, 방법을 배울 수를 읽을 수 있습니다

참조 카운트를 상세히 추적하는 데 도움이되는 Python 빌드를 만들 수 있습니다.

개체에 대한 특정 개수의 참조에만 의존해서는 안됩니다. 함수 오브젝트에 접근하여 더 많은 참조를 사용자 오브젝트에 추가 할 수 있습니다 (예 : foo = normal_te_st.__code__.co_conts[1]은 함수를 실행하기 전에 참조 카운트를 증가시킵니다). 참조 카운트를 정확히 올리려면 구현 세부 사항이 필요합니다. 자신의 코드이 참조를 올바르게 처리하는지 확인하십시오.

+0

참고 자료를 보내 주셔서 감사합니다.하지만이 답변은 내가 원하는 것입니다. – jcr

관련 문제