如何查找Python模块源代码的位置?

608

我该如何学习一个给定的Python模块源文件安装在哪里?在Windows和Linux上的方法是否不同?

我尝试查找特定的datetime模块的源代码,但我也对更通用的答案感兴趣。

21个回答

456

对于一个纯Python模块,您可以通过查看themodule.__file__来找到源代码。 然而,datetime模块是用C编写的,因此datetime.__file__指向.so文件(在Windows上没有datetime.__file__),因此您无法查看源代码。

如果您下载了Python源代码压缩包并将其解压,则可以在 Modules 子目录中找到模块的代码。

例如,如果您想找到Python 2.6的datetime代码,可以查看

Python-2.6/Modules/datetimemodule.c

您还可以在github网站上找到此文件的最新版本,链接为https://github.com/python/cpython/blob/main/Modules/_datetimemodule.c


如果您编辑您的答案以指示datetime.__file__在Linux和Mac OS X上指向.so(尽管在Windows上,datetime模块对象没有__file__属性),我将接受您的答案。 - Daryl Spitzer
实际上在Windows上(至少在我使用的版本上),datetime模块没有__file__属性。 - Daryl Spitzer
1
非常适用于自行安装的模块。 - fytao

270

从命令行运行python -v命令应该会告诉你正在导入的内容以及它们的来源。在Windows和Mac OS X上,这对我有效。

C:\>python -v
# installing zipimport hook
import zipimport # builtin
# installed zipimport hook
# C:\Python24\lib\site.pyc has bad mtime
import site # from C:\Python24\lib\site.py
# wrote C:\Python24\lib\site.pyc
# C:\Python24\lib\os.pyc has bad mtime
import os # from C:\Python24\lib\os.py
# wrote C:\Python24\lib\os.pyc
import nt # builtin
# C:\Python24\lib\ntpath.pyc has bad mtime
...

我不确定我的安装中那些坏的mtime是什么!


11
酷!当它在交互模式下打开后,您还可以输入自己特定的import语句,以查看特定库来自哪里。 - scorpiodawg
7
内置模块在哪里? - loretoparisi
对于MacOS用户,请输入python3 -v。您将获得命令结果。 - Lalarukh khan

151

我知道这个答案晚了4年,但现有的答案会误导人。

正确的方法从不是__file__,也不是尝试遍历 sys.path 并搜索自己(除非你需要向后兼容2.1及以前的版本)。

应该使用inspect模块,特别是getfilegetsourcefile函数。

除非你想学习和实现规则(这些规则对于CPython 2.x来说已经有文件记录,但很痛苦,并且其他实现方式或3.x没有文件记录),将.pyc映射到.py文件;处理.zip归档、egg和模块包;尝试不支持__file__的路径获取.so/.pyd文件的不同方法;弄清楚Jython/IronPython/PyPy等的工作原理。如果你想这样做,请继续。

与此同时,从Python 2.0版本开始的每个版本的源代码都可以在网上找到,网址是http://hg.python.org/cpython/file/X.Y/(例如,2.73.3)。因此,一旦你发现inspect.getfile(datetime)是一个.so.pyd文件,例如/usr/local/lib/python2.7/lib-dynload/datetime.so,你可以在Modules目录中查找它。严格来说,并没有确切的方法可以确定哪个文件定义了哪个模块,但几乎所有的文件要么是foo.c,要么是foomodule.c,所以猜测datetimemodule.c就是你想要的。


3
为什么非内置模块不适用于__file__?我理解在没有了解meta_path的情况下,爬取sys.path可能会很麻烦,但你是否关注于__file__定义和二进制文件之间的命名空间问题? - user559633
2
我在2.7.8上使用datetime,但是无论是getfile还是getsourcefile都会出现TypeError。就我个人而言,我安装了多个版本的Python,并且我需要知道它指向哪个datetimemodule.c版本,因为现在我知道它没有指向应该指向的那个解释器版本... - mmitchell
1
如果你从 inspect.getfile(datetime) 获得了一个 TypeError,假设 datetime 实际上是模块而不是你分配给相同名称的其他东西,那么我很确定这意味着你制作了一个自定义版本来静态链接 datetime 到解释器中,而不是将其作为可加载的模块。但也可能有其他我没有想到的原因。你需要提出一个新问题,并提供更多信息来复现这个问题。 - abarnert
@tristan:我不确定我理解你的问题,但也许这会回答它:无论何时__file__有效,inspect.getfile都有效;没有猜测是否使用__file__比使用inspect模块更好的情况。 - abarnert
1
是的,我知道编译是如何工作的,我只是为了与你的答案保持一致而使用了“.c”。;) 我也没有期望你能完全解决我的问题,只是想指出你的答案不起作用。我在一个干净的、原始的2.7.8安装上进行了测试,并得到了错误提示,所以这与自定义内容无关——它在Windows上就是不起作用。 - mmitchell
显示剩余4条评论

134
如果您使用pip安装模块,只需运行pip show $module命令,就可以返回所在位置。

19
我认为$module是指占位变量,而不是字面上要键入的内容。例如,对于任何m,都可以输入m=numpy; pip show $m等等。 - michael
1
这应该是最准确的答案。 - Rahul Goyal
3
实际上,如果您安装了多个Python,则此方法不可靠,因为从shell执行的pip可能与在python中调用的不同。相反,您应该执行python -m pip show $module。请参见umesh的答案 - wisbucky

81

sys.path 列表包含在运行时搜索模块的目录列表:

python -v
>>> import sys
>>> sys.path
['', '/usr/local/lib/python25.zip', '/usr/local/lib/python2.5', ... ]

11
python -c 'import sys; print "\n".join(sys.path)'可以让您查看Python模块搜索路径,而无需进入交互式Python环境。 - Joe Block
7
Python 3:python -c'import sys; print("\n".join(sys.path))' - arudzinska

55

从标准库中尝试使用imp.find_module

>>> import imp
>>> imp.find_module('fontTools')
(None, 'C:\\Python27\\lib\\site-packages\\FontTools\\fontTools', ('', '', 5))
>>> imp.find_module('datetime')
(None, 'datetime', ('', '', 6))

1
这太棒了。我使用 apt-get remove 删除了 DataDog,但仍然可以导入它。这帮助我找到文件在哪里(以便我可以删除它们),而其他解决方案没有帮助。 - s g
1
对于Python3.x,imp包已被弃用(自3.4版本起),建议使用importlib(自3.1版本起)。详见https://docs.python.org/3.6/library/imp.html。 - michael
6
现在您需要按照以下方式在Python3中使用它:首先导入importlib,然后使用importlib.util.find_spec('fontTools') - Medhat
这是答案。如果在激活虚拟环境时运行Python交互会话,您可以获得VE中的模块和基础Python安装中的模块的详细信息,而不像python -m pip show xxx只显示已通过pip安装的模块。确认imp已被弃用,并“计划在Python 3.12中删除”。 - mike rodent

47

datetime是Python内置模块,因此没有(Python)源文件。

对于来自.py(或.pyc)文件的模块,您可以使用mymodule.__file__,例如:

> import random
> random.__file__
'C:\\Python25\\lib\\random.pyc'

14
获取模块文件名的一行代码,适合用于 shell 命令别名:
echo 'import sys; t=__import__(sys.argv[1],fromlist=[\".\"]); print(t.__file__)'  | python - 

设置别名:

alias getpmpath="echo 'import sys; t=__import__(sys.argv[1],fromlist=[\".\"]); print(t.__file__)'  | python - "

使用方法:

$ getpmpath twisted
/usr/lib64/python2.6/site-packages/twisted/__init__.pyc
$ getpmpath twisted.web
/usr/lib64/python2.6/site-packages/twisted/web/__init__.pyc

第一个版本是错误的,反斜杠太多了。从shell脚本运行,这对我有效:echo 'import sys; t=__import__(sys.argv[1],fromlist=["."]); print(t.__file__)' | python - "$@" - Metamorphic

13

在Python解释器中,您可以导入特定的模块,然后键入 help(module)。这会提供诸如名称、文件、模块文档、描述等详细信息。

例如:

import os

help(os)


Help on module os:

NAME

os - OS routines for Mac, NT, or Posix depending on what system we're on.

FILE

/usr/lib/python2.6/os.py

MODULE DOCS

http://docs.python.org/library/os

DESCRIPTION

This exports:

- all functions from posix, nt, os2, or ce, e.g. unlink, stat, etc.

- os.path is one of the modules posixpath, or ntpath

- os.name is 'posix', 'nt', 'os2', 'ce' or 'riscos'

et al

:等人,常用于引用文献而不列举所有作者的情况。

这让我得到了模块文件的完整路径,而其他答案只给出了相对路径。谢谢。 - Jerther

13

在Windows上,您可以按照以下方式找到Python模块的位置,例如查找rest_framework模块:enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接