Python 3.x 查找用C实现的方法的源代码?

Python 3.x 查找用C实现的方法的源代码?,python-3.x,cpython,python-internals,Python 3.x,Cpython,Python Internals,请注意,我问这个问题只是为了提供信息 我知道这个标题听起来像是一个复制品。但让我解释一下 例如,我想找到集合.Counter的最常用的方法的源代码。由于计数器类是用python实现的,所以我可以使用检查模块获取它的源代码 即 这会打印出来 def most_common(self, n=None): '''List the n most common elements and their counts from the most common to the

请注意,我问这个问题只是为了提供信息

我知道这个标题听起来像是一个复制品。但让我解释一下

例如,我想找到
集合.Counter的
最常用的
方法的源代码。由于
计数器
类是用python实现的,所以我可以使用
检查
模块获取它的源代码

这会打印出来

    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))
因此,如果方法或类是在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.

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

首先也是最重要的,绝大多数Python安装都不包含C源代码。接下来,虽然可以想象Python语言的用户能够阅读Python源代码,但Python的用户基础非常广泛,很多人不了解C或对C代码的工作方式感兴趣,最后,即使知道C的开发人员也不必阅读,如果您想了解Python代码库,那么很快就会需要一些东西

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

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

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


或者,下载Python源代码并创建调试版本,并使用良好的IDE帮助您将符号等映射回源文件。不同的编译器、平台和IDE有不同的方法来支持用于调试的符号表。

如果您有完整的调试信息(通常是剥离的),可能会有一种方法


然后,您将访问
so
pyd
,并使用特定于平台的工具提取所需功能的调试信息(存储在
so
或Windows上的
pdb
中)。您可能想看看Linux的DWARF信息(在Windows上,目前还没有文档)。

我认为答案可能是否定的,除非您对GitHub进行某种删减或反编译,因为您的本地计算机上可能根本不存在该源代码。C代码是在构建python发行版时编译的,您可能没有可用的C源文件。我很想知道我错了,不过我会密切关注这个问题。即使在调试版本中,也没有足够的信息可以直接映射到源文件。而且分析器可以做到这一点(callgrind、tune…),gdb也可以。不是说这很容易,而是说这是可行的。如果您有源文件,效果会更好。
>>> 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.
>> 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;
}