Python 如何获取模块中类的定义?

Python 如何获取模块中类的定义?,python,python-3.x,Python,Python 3.x,为什么我不能在下面的代码中从模块集合中获取可调用的定义 如何获取模块中类的定义?谢谢 >>> from collections import Callable >>> inspect.getsource(Callable) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python3.5/inspect.

为什么我不能在下面的代码中从模块
集合
中获取
可调用
的定义

如何获取模块中类的定义?谢谢

>>> from collections import Callable
>>> inspect.getsource(Callable)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/inspect.py", line 944, in getsource
    lines, lnum = getsourcelines(object)
  File "/usr/lib/python3.5/inspect.py", line 931, in getsourcelines
    lines, lnum = findsource(object)
  File "/usr/lib/python3.5/inspect.py", line 788, in findsource
    raise OSError('could not find class definition')
OSError: could not find class definition
>>> inspect.getsourcelines(Callable)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/inspect.py", line 931, in getsourcelines
    lines, lnum = findsource(object)
  File "/usr/lib/python3.5/inspect.py", line 788, in findsource
    raise OSError('could not find class definition')
OSError: could not find class definition
>>> inspect.getmodule(Callable)
<module 'collections.abc' from '/usr/lib/python3.5/collections/abc.py'>
>>> inspect.getfile(Callable)
'/usr/lib/python3.5/collections/abc.py'
>>> inspect.getsourcefile(Callable)
'/usr/lib/python3.5/collections/abc.py'
>>从集合导入可调用
>>>inspect.getsource(可调用)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/usr/lib/python3.5/inspect.py”,第944行,在getsource中
行,lnum=getsourcelines(对象)
文件“/usr/lib/python3.5/inspect.py”,第931行,在getsourcelines中
行,lnum=findsource(对象)
文件“/usr/lib/python3.5/inspect.py”,第788行,在findsource中
raise OSError('找不到类定义')
OSError:找不到类定义
>>>inspect.getsourcelines(可调用)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/usr/lib/python3.5/inspect.py”,第931行,在getsourcelines中
行,lnum=findsource(对象)
文件“/usr/lib/python3.5/inspect.py”,第788行,在findsource中
raise OSError('找不到类定义')
OSError:找不到类定义
>>>inspect.getmodule(可调用)
>>>inspect.getfile(可调用)
“/usr/lib/python3.5/collections/abc.py”
>>>inspect.getsourcefile(可调用)
“/usr/lib/python3.5/collections/abc.py”
获取源代码(全名)
返回指定模块的源代码

因此,您应该返回整个模块,因为在
\u collections\u abc
的模块中定义了
可调用的
,因此您的代码应该是:

import _collections_abc

import inspect

print(inspect.getsource(_collections_abc))

您可以在打印结果中看到
可调用的定义。

通常,这很容易完成,它接受一个模块、一个类、一个方法、一个函数、一个回溯、一个帧、, 或代码对象。它们所代表的源代码当然应该用Python编写,否则会出现错误

在这种特殊情况下,您恰好运气不好,因为
可调用
是在
\u collections\u abc
中定义的:

这会使
getsource
关闭,因为它不会在包含
Callable
s定义的
\u collections\u abc
中查找,而是在
collections.abc
中查找。abc
仅从
\u collections\u abc
导入所有定义:

>>> print(getsource(collections.abc))
from _collections_abc import *
from _collections_abc import __all__
通常,
getsource
在查找源代码时没有问题,例如,在其自身上:

>>> print(getsource(getsource))
def getsource(object):
    """Return the text of the source code for an object.

    The argument may be a module, class, method, function, traceback, frame,
    or code object.  The source code is returned as a single string.  An
    OSError is raised if the source code cannot be retrieved."""
    lines, lnum = getsourcelines(object)
    return ''.join(lines)
但是,在这种特定情况下,它确实存在(由于
可调用。\uuuuu模块\uuuuu
返回
集合.abc
),您可以用
替换
\uuuu模块\uuuuuu
,以一种巧妙的方式查看源代码:

>>> Callable.__module__ = '_collections_abc'
>>> src = getsource(Callable)  
>>> print(src)
class Callable(metaclass=ABCMeta):

    __slots__ = ()

    @abstractmethod
    def __call__(self, *args, **kwds):
        return False

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Callable:
            return _check_methods(C, "__call__")
        return NotImplemented

但这让我感觉不太舒服。

谢谢。您的意思是
inspect.getsource
只能应用于模块对象吗?我看到它可以应用于函数对象来获得函数的定义。那么为什么它不适用于类
inspect.Callable
?也许您提到的函数被定义为一个模块?不确定,但我粘贴的getsource的定义来自官方文档。谢谢。是否通过
obj.\uu模块\uuu
查找对象的定义
obj
?那么,它们是否需要用Python而不是二进制代码定义
obj
getfile
是否也通过
obj.\uuu模块\uuuu
查找对象的文件
obj
?@Tim是的,
getsourceline
getsource
都在内部使用
getfile
obj
抓取
\uu模块
,如果这是一个类的话(哪个inspect通过使用
inspect.isclass
)来确定)。内置模块(在CPython的情况下用C实现)不能与
inspect
一起使用,因此必须在Python中定义它们。
>>> Callable.__module__ = '_collections_abc'
>>> src = getsource(Callable)  
>>> print(src)
class Callable(metaclass=ABCMeta):

    __slots__ = ()

    @abstractmethod
    def __call__(self, *args, **kwds):
        return False

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Callable:
            return _check_methods(C, "__call__")
        return NotImplemented