AttributeError: module ‘matplotlib‘ has no attribute ‘pyplot‘
回来了很久没有更新博客了,上了研究生之后,科研任务蛮重的,还要兼顾学习任务,有时候想写写博客记录记录学习内容,总结总结学习心得什么的,都难有时间。本科的时候博客大部分内容偏向于实践,尤其是Web方面的实践内容,因为当时想着好找工作,又比较喜欢就自己有事没事钻研学习。现在读研了,不太想继续搞前端了,目前正在努力的方向是大数据、数据分析、数据挖掘之类的方向(属于算法方向,对我来说还是比较困难,不过没关
回来了
很久没有更新博客了,上了研究生之后,科研任务蛮重的,还要兼顾学习任务,有时候想写写博客记录记录学习内容,总结总结学习心得什么的,都难有时间。
本科的时候博客大部分内容偏向于实践,尤其是Web方面的实践内容,因为当时想着好找工作,又比较喜欢就自己有事没事钻研学习。现在读研了,不太想继续搞前端了,目前正在努力的方向是大数据、数据分析、数据挖掘之类的方向(属于算法方向,对我来说还是比较困难,不过没关系,把时间花在做上就好了)。所以前端、Web相关的博客可能会减少了,但是实践风格依然不变,我还是喜欢做做东西比较实在,当然,也会写一些偏理论的文章,毕竟搞研究嘛,理论还是得有些积累。
使用matplotlib遇到了问题
matplotlib是python中用来对标matlab的一个绘图库,可以方便的画各种科学计算图。最近有科研需求需要用到matplotlib库,但是在导入使用matplotlib库是遇到了比较诡异的问题。
官方文档中给出的引入matplotlib的方式如下:
import matplotlib.pyplot as plt
这样本身是没有什么问题的,plt可以正常访问pyplot模块中的各种接口。但是当我尝试想下面这样引入时,遇到了 AttributeError: module 'matplotlib' has no attribute 'pyplot'
的问题。
import matplotlib
plt = matplotlib.pyplot
这是为什么呢?我又尝试如下引用方式,并对两次引用的pyplot比较,看是否是同一个对象:
import matplotlib.pyplot as plt
import matplotlib as mpl
if plt is mpl.pyplot:
print('True')
else:
print('False')
神奇的是,这一次mpl.pyplot
没有报错,且输出为True
。也就是说,这一次pyplot
在matplotlib
命名空间中存在了,且就是我们第一行导入的那个pyplot
。这是为什么呢?
正解
为了搞清楚其中的原理,我特地去看了看matplotlib源码包。想知道matplotlib源码放在哪里?在python交互式模式下输入以下代码即可知道位置:
>>> import matplotlib
>>> matplotlib
<module 'matplotlib' from 'C:\\Users\\angelavor\\anaconda3\\envs\\ML\\lib\\site-packages\\matplotlib\\__init__.py'>
转到matplotlib源码相应位置,可以看到其源码结构如下:
整个源码还是比较庞大的,我们只需要看几个关键文件及其结构:
matplotlib
|_______ axes
|_______ __init__.py
|_______ ......
|_______ pyplot.py
首先明确两个概念——包和模块。包是python组织模块的一种方式,简单来说,包就是文件夹,包中放许多模块。模块是python组织源码的一种方式,简单来说,模块就是一个py文件。所以这里,matplotlib
和pyplot
的关系就是包与其模块的关系。
那import
的语句是如何识别出包和模块的呢?关键就是 __init__.py
文件,有关python模块化中__init__.py
的作用这里有两篇博客写的很好(链接通道1 、 链接通道2),可以参考。
简单来说,一个文件夹下只有存在__init__.py
才能被识别为一个可导入的python包。导入包其实是导入此包下的__init__.py
模块。所以,__init__.py
也起到初始化包的作用,事实上,导入包的时候会执行此脚本,初始化参数并加载一些需要的模块。
默认情况下,__init__.py
可以什么也不写,只起到标识python包的作用,但是这个时候仅仅导入包是什么都做不了的,因为没有任何模块预加载。这里pyplot
模块之所以没能通过引入matplotlib
来引入,是因为其__init__.py
中根本就没有加载引入pyplot
模块 !!!
又因为pyplot
是属于matplotlib
命名空间下的,因此一旦显式导入模块,它就自动加入matplotlib
命名空间下了。这也就解释了开头出现的比较诡异的问题。
总结一下
-
直接引入
matplotlib
包是不能引入pyplot
模块的 -
官方推荐直接引入
matplotlib.pyplot
,原因其实可以在__init__.py
源码中的文档注释找到答案。我这里引用一下这些注释。A procedural interface is provided by the companion pyplot module,which may be imported directly, e.g.::
import matplotlib.pyplot as pltFor the most part, direct use of the object-oriented library is encouraged when
programming; pyplot is primarily for working interactively. The exceptions are
the pyplot functions.pyplot.figure
,.pyplot.subplot
,.pyplot.subplots
,
and.pyplot.savefig
, which can greatly simplify scripting.翻译一下,就是
pyplot
模块里整合了matplotlib
库里的画图接口。大部分情况下,在编写程序中推荐使用面向对象的方式;但是在交互式模式下,可以通过pyplot函数
快速的上手绘图。 -
如果想避免出现找不到module的问题,可以把
matplotlib
和matplotlib.pyplot
都引入,想下面这样即可:import matplotlib.pyplot as plt import matplotlib as mpl
收工!睡觉~
更多推荐
所有评论(0)