2010-01-05 5 views
4

런타임에 동적으로 정의 된 함수를 디버깅하는 방법이 있습니까?파이썬에서 동적으로 정의 된 함수를 디버깅하는 방법은 무엇입니까?

또는 적어도이 함수가 생성 된 위치를 쉽게 찾을 수 있습니까?

요금보다 상세히을 얻었다 : 여기 inspect

ipdb> inspect.getmodule(im.get_thumbnail_url) 
Out[0]: <module 'django.utils.functional' from 'C:\java\python\Python25\Lib\site 
-packages\django\utils\functional.pyc'> 
ipdb> inspect.getsource(im.get_thumbnail_url) 
Out[0]: ' def _curried(*moreargs, **morekwargs):\n  return _curried_fun 
c(*(args+moreargs), **dict(kwargs, **morekwargs))\n' 

가 pinax의 get_thumbnail_url 방법 photos.models.Image의 클래스 django.utils.functional.curry._curried 함수에 의해 생성되는 것을 보여준다

제가 inspect 모듈을 사용 하였다. 하지만 여전히 방법이 어디서 생산되는지, 즉 _curried 함수가 호출 된 위치를 표시하지 않습니다. 이 정보는 get_thumbnail_url이 어떻게 구현되는지 알아내는 데 필요합니다.

_curried 내부에 pdb을 넣을 수 있지만 매우 자주 사용되는 함수 호출이기 때문에 거기에서 여러 번 분해됩니다. 중단 점 조건을 사용하려면 몇 가지 고유 한 기능이 필요합니다. 솔루션에 대해

업데이트 : 모든 제안

감사합니다. 해결책을 찾았습니다. 내가 그것을 어떻게 찾았는지 설명하겠습니다. 어쩌면 다른 사람들을 도울 것입니다 :

첫째, 나는 pinax 소스 코드에서 'get_thumbnail_url'용어를 검색했습니다. 결과가 없다. 두 번째로, 나는 pinax 소스 코드에서 'thumbnail'용어를 검색했다. 유용한 결과가 없습니다. 마지막으로, 나는 pinax 소스 코드에서 'curry'용어를 검색했습니다.

def add_accessor_methods(self, *args, **kwargs): 
    for size in PhotoSizeCache().sizes.keys(): 
     setattr(self, 'get_%s_size' % size, 
       curry(self._get_SIZE_size, size=size)) 
     setattr(self, 'get_%s_photosize' % size, 
       curry(self._get_SIZE_photosize, size=size)) 
     setattr(self, 'get_%s_url' % size, 
       curry(self._get_SIZE_url, size=size)) 
     setattr(self, 'get_%s_filename' % size, 
       curry(self._get_SIZE_filename, size=size)) 

get_thumbnail_url 방법이 호출에 의해 생성된다 : curry(self._get_SIZE_url, size=size)) 다음은 몇 가지 결과 중 하나였다.

물론 이것은 일반적인 해결책 방법이 아닙니다. 동적으로 정의 된 함수가 실제로 어디서 만들어 지는지 확인하는 다른 방법을 공유 할 수 있다면 큰 도움이 될 것입니다.

편집 :

가장 general solution는 제이슨 Orendorff 아래에 기록됩니다.

+0

"동적 정의 함수"란 정확히 무엇을 의미합니까? 이것은'lambda' 함수인가,'exec ("def foo() : return bar")'또는 이와 비슷한 것입니까? –

+0

특히, 지금 인트로 스펙 트하려고하는 함수는 카레 함수입니다. 나는 그것이 λ 함수이거나 exec에 의해 생성 된 함수라고 생각하지 않는다. 나는 그것이 그것이 어디에서 생산되는지를 모르기 때문에 그것이 어떻게 정확하게 정의되어 있는지 모른다. 하지만 저자가 일종의 파견을했다고 생각합니다. –

+0

몇 가지 샘플 코드를 게시 할 수 있습니까? – richo

답변

1

을 감안할를 함수 f, CPython에서 f.func_code.co_filenamef.func_code.co_firstlineno을 인쇄하여 파일과 첫 번째 줄 번호를 가져올 수 있습니다. 함수가 eval 또는 exec을 사용하여 생성 된 경우에는 도움이되지 않습니다.

추적 정보에는 파일 및 회선 정보도 들어 있습니다.

import disdis.dis(f)을 사용하면 CPython 바이트 코드를 볼 수 있습니다. 이 방법은 유용하지 않을 수 있지만 올바른 위치로가는 길을 찾는 데 도움이되는 문자열을 보여줄 수 있습니다.

또 다른 한가지는 파이썬 텍스트 모드 디버거 인 PDB입니다. 예외 후, import pdb; pdb.pm()은 PDB를 시작합니다. 원시적이지만 유용합니다. 명령 목록을 보려면 help을 입력하십시오. where은 스택을 보여줍니다.

편집 :이 기능은 카레입니다. functools.partial을 사용하여 만든 경우 기본 기능을 나타내는 .func 특성이 있습니다.

편집 2 : 일반적인 방법이 될 것im.get_thumbnail_url에 중단 점을 설정 한 후 즉시 호출. 중단 점이 즉시 중지됩니다. 당신은 당신이 관심있는 코드에 도달 할 때까지 다음 단계

카레 기능,이 경우처럼 코드에 의해 생성 된 이후 :. 다른 방법은 다음과 같이 f.func_closure을 검토하는 것입니다

def curry(_curried_func, *args, **kwargs): 
    def _curried(*moreargs, **morekwargs): 
     return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs)) 
    return _curried 

:

>>> f 
<function _curried at 0xb77d64fc> 
>>> f.func_closure 
(<cell at 0xb77eb44c: tuple object at 0xb77dfa0c>, <cell at 0xb77eb5e4: dict object at 0xb77d93e4>, <cell at 0xb77eb5cc: function object at 0xb77d1d84>) 

이 함수는 튜플, 사전 및 함수의 세 변수를 닫습니다. 분명히이 함수는 우리가 관심이있는 함수입니다 (그러나이 세 셀은 args, kwargs_curried_func에 해당하며 둘러싸 기 함수 curry에 정의되어 있지만 닫음 _curried에서 사용됨).

>>> f.func_closure[2].cell_contents 
<function say at 0xb77d1d84> 
>>> import inspect 
>>> inspect.getsource(_) 
'def say(x):\n print x\n' 
1

확실하지,하지만 당신은 그것이 검사 모듈을 사용하여 정의 된 소스 파일과 줄 번호를 출력하는 함수를 얻을 수 있습니다 :

import inspect 
f = lambda: inspect.currentframe().f_code.co_filename + ':' + \ 
    str(inspect.currentframe().f_lineno); 
print f() 

그것은 인쇄하십시오

script.py:2 
관련 문제