如何在Python中调试动态定义的函数?

有没有办法调试在运行时动态定义的函数?

或者至少有一种简单的方法可以找出这个函数的产生位置?

更新以提供更多详细信息:

我用过检查模块:

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'

这里inspect检查显示pinax的photos.models.Image类的get_thumbnail_url方法是由django.utils.functional.curry._curried函数生成的.但是它仍然没有显示方法的产生位置,即被称为_curried函数的位置.此信息对于了解如何实现get_thumbnail_url是必要的.

我可以将pdb放在_curried函数中,但之后它会中断很多次因为这是一个非常常用的函数调用.我需要有一些区别特征来使用断点条件.

更新解决方案:

谢谢你的所有建议.我找到了解决方案.让我解释一下我是如何找到它的.也许它会帮助其他人:

首先,我在pinax源代码中搜索了’get_thumbnail_url’一词.没有结果.
其次,我在pinax源代码中搜索了“缩略图”术语.没有用的结果.
最后,我在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由Jason Orendorff撰写如下.

最佳答案 给定函数f,在CPython中,您可以打印f.func_code.co_filename和f.func_code.co_firstlineno来获取文件和第一行号.如果使用eval或exec创建函数,这将无济于事.

回溯还包含文件和行信息.

如果你import dis你可以使用dis.dis(f)来查看CPython字节码;这可能没用,但它可能会显示一些字符串,帮助您找到通往正确位置的方法.

另一件需要关注的是PDB,Python文本模式调试器.异常后,导入pdb; pdb.pm()启动PDB.这是原始的,但很有用;键入帮助以获取命令列表.在哪里显示堆栈.

编辑:你提到这是一个curried功能.如果它是使用functools.partial创建的,那么它有一个引用底层函数的.func属性.

编辑2:一般的方法是在im.get_thumbnail_url上设置一个断点,然后立即调用它.你的断点应立即发出.然后一步一步,直到找到您感兴趣的代码.

由于curried函数在这种情况下由代码生成,如:

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

另一种方法是检查f.func_closure,如下所示:

>>> 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'
点赞