查找用 C 语言实现的方法的源代码?



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

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

例如,我想找到collections.Countermost_common方法的源代码。由于Counter类是用python实现的,我可以使用inspect模块获取它的源代码。

即,

>>> import inspect
>>> import collections
>>> print(inspect.getsource(collections.Counter.most_common))

这将打印

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:Usersabdul.niyasAppDataLocalProgramsPythonPython36-32libinspect.py", line 968, in getsource
lines, lnum = getsourcelines(object)
File "C:Usersabdul.niyasAppDataLocalProgramsPythonPython36-32libinspect.py", line 955, in getsourcelines
lines, lnum = findsource(object)
File "C:Usersabdul.niyasAppDataLocalProgramsPythonPython36-32libinspect.py", line 768, in findsource
file = getsourcefile(object)
File "C:Usersabdul.niyasAppDataLocalProgramsPythonPython36-32libinspect.py", line 684, in getsourcefile
filename = getfile(object)
File "C:Usersabdul.niyasAppDataLocalProgramsPythonPython36-32libinspect.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.

所以我的问题是,有没有办法(或使用第三方包?(我们也可以找到用 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;
}

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

首先,绝大多数Python安装不包括C源代码。接下来,虽然你可以想象Python语言的用户能够阅读Python源代码,但Python的用户群非常广泛,很多人不懂C或对C代码的工作原理感兴趣,最后,即使是知道C的开发人员也不能指望必须阅读Python C API文档, 如果你想了解 Python 代码库,很快就会成为一项要求。

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

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

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

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

如果你有完整的调试信息(通常被剥离(,可能会有一种方法。

然后,您将进入sopyd,并使用特定于平台的工具提取所需功能的调试信息(存储在Windows上的sopdb中(。你可能想看看Linux的DWARF信息(在Windows上,没有文档AFAIK(。

最新更新