查找C中实现的方法的源代码?

Abd*_*P M 2 cpython python-3.x python-internals

请注意,我这个问题仅供参考

我知道标题听起来像是查找内置Python函数的源代码的副本.但让我解释一下.

比方说,我想找到类most_common方法的源代码collections.Counter.由于Counter该类是在python中实现的,我可以使用该inspect模块获取它的源代码.

>>> import inspect
>>> import collections
>>> print(inspect.getsource(collections.Counter.most_common))
Run Code Online (Sandbox Code Playgroud)

这将打印

    def most_common(self, n=None):
        '''List the n most common elements and their counts from the most
        common to the least.  If n is None, then list all element counts.

        >>> Counter('abcdeabcdabcaba').most_common(3)
        [('a', 5), ('b', 4), ('c', 3)]

        '''
        # Emulate Bag.sortedByCount from Smalltalk
        if n is None:
            return sorted(self.items(), key=_itemgetter(1), reverse=True)
        return _heapq.nlargest(n, self.items(), key=_itemgetter(1))
Run Code Online (Sandbox Code Playgroud)

因此,如果在C中实现的方法或类inspect.getsource将引发TypeError.

>>> my_list = []
>>> print(inspect.getsource(my_list.append))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\abdul.niyas\AppData\Local\Programs\Python\Python36-32\lib\inspect.py", line 968, in getsource
    lines, lnum = getsourcelines(object)
  File "C:\Users\abdul.niyas\AppData\Local\Programs\Python\Python36-32\lib\inspect.py", line 955, in getsourcelines
    lines, lnum = findsource(object)
  File "C:\Users\abdul.niyas\AppData\Local\Programs\Python\Python36-32\lib\inspect.py", line 768, in findsource
    file = getsourcefile(object)
  File "C:\Users\abdul.niyas\AppData\Local\Programs\Python\Python36-32\lib\inspect.py", line 684, in getsourcefile
    filename = getfile(object)
  File "C:\Users\abdul.niyas\AppData\Local\Programs\Python\Python36-32\lib\inspect.py", line 666, in getfile
    'function, traceback, frame, or code object'.format(object))
TypeError: <built-in method append of list object at 0x00D3A378> is not a module, class, method, function, traceback, frame, or code object.
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,是否有任何方法(或使用第三方包?)我们可以找到在C中实现的类或方法的源代码?

即,像这样的事情

>> print(some_how_or_some_custom_package([].append))


int
PyList_Append(PyObject *op, PyObject *newitem)
{
    if (PyList_Check(op) && (newitem != NULL))
        return app1((PyListObject *)op, newitem);
    PyErr_BadInternalCall();
    return -1;
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 7

不,那里没有.没有可从Python访问的元数据,可以让您找到原始源文件.这些元数据必须由Python开发人员显式创建,而没有明显的好处.

首先,绝大多数Python安装都不包含C源代码.接下来,虽然您可以想象Python语言的用户能够阅读Python源代码,但Python的用户库非常广泛且大量不知道C或者对C代码的工作方式感兴趣,最后,甚至是开发人员知道C不能指望阅读Python C API文档,如果你想了解Python代码库,很快就会成为一个要求.

与Python字节码缓存文件和脚本不同,C文件不直接映射到特定的输出文件.除非您使用符号表创建调试版本,否则编译器不会在其生成的生成的目标文件(.o)中保留源文件名,链接器也不会记录.o它生成的结果中的文件.所有C文件最终都不会对同一个可执行文件或动态共享对象文件做出贡献; 有些成为Python二进制文件的一部分,其他成为可加载的扩展,混合是可配置的,并且取决于编译时可用的外部库.

在makefile setup.py和C pre-propressor宏之间,输入文件和实际用于创建每个输出文件的源代码行的组合也各不相同.最后但并非最不重要的是,因为在运行时不再查询C源文件,所以不能指望它们仍然在相同的原始位置可用,因此即使存储了一些元数据,您仍然无法将其映射回原本的.

因此,只需记住一些关于Python C-API如何工作的基本规则,然后通过一些明智的代码搜索将其映射回C代码就更容易了.

或者,下载Python源代码并创建调试版本,并使用一个好的IDE来帮助您将符号映射到源文件.不同的编译器,平台和IDE具有支持符号表进行调试的不同方法.