ExASIC
分享让工作更轻松

python的模块module介绍

我们知道,Verilog语言的模块是最底层的功能部件,底层模块在其它模块里被例化,然后又在顶层模块里被例化。这样一级级、一层层构成了一个大项目。

概要:

模块是一块积木

在python语言里也一样,模块是最基本的功能单位。我们写一个python脚本,通常需要导入(import)其它模块。比如,如果我们打算获取命令行参数,就需要import sys。如果我们打算新建文件夹,就需要import os。又如果我们打算使用科学计算,就需要import numpy。在python的PyPI ( https://pypi.python.org/pypi ) 里的第三方模块包已经超过12万个。所以绝大部分时候,我们并不需要从零开始造轮子。

一切都是以模块的形式存在的

在python里,一切都是以模块的形式存在的。可能有人反驳道,他写了一个最简单的Hello world脚本(如下面的hello_world.py),并没有用到、也没有导入任何其它模块。

print("Hello world") #仅此一行

但实际情况是什么呢?python解释器在启动的时候已经帮我们自动导入一个名叫builtins的模块。我们用dir()来帮助理解这一点。在python命令行里输入dir(__builtins__),输出如下的列表:

>>> dir(__builtins__)
[..., 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

是不是发现了这里面包括了print函数?此处稍微思考一会儿。。。很神奇是吧。是不是还发现了很多常用的函数?所以,不需要导入任何模块就可以直接使用的函数正是builtins模块中的函数。

之前讲函数作用域时讲过,查找变量的规则是“由内向外、由近及远”。这里的“远”就是指builtins模块。如果一直找到builtins模块,仍然没有找到变量的定义,就会报变量未定义的错误。

再来理解if __name__ == '__main__'

一般来说,在python里模块名字就是文件名。我们可以通过内置变量name来读取模块名。例如:

>>> print(__name__)
__main__
>>> import sys
>>> print(sys.__name__)
sys
>>> import os
>>> print(os.__name__)
os

当前正在执行的脚本被赋予的模块名字是__main__,相当于C语言的入口函数main()。在《我的第一个Python程序》里,我们写了如下图的程序。我们判断模块的名字是不是__main__来决定要不要调用main(argv)函数。这样写的好处是什么呢?当这个脚本被当作模块来做集成时,模块名是文件名hello(而__main__变成是import hello模块的上层脚本),if __name__ == '__main__'条件里面的语句不会执行。

import sys

def main(argv):
    print("hello " + argv[1] + "!")

if __name__ == '__main__':
    main(sys.argv)

如果没有if __name__ == '__main__'这一行,在被其它模块导入后,main(argv)会执行两次。

例如下面的例子,有hello_world.py和test.py,位于同一个目录下。

#hello_world.py
def print_hello():
    print("hello world")
print_hello()  #没有放在if里

#test.py
import hello_world
hello_world.print_hello() #调用函数

结果输出
$ python test.py
hello world
hello world
输出了两次hello world?你没看错。一次是hello_world.py里的,另一次是test.py里的。

所以,if __name__ == '__main__'这句的作用就是,让脚本既可以直接当作执行脚本,又可以作当模块被导入。

模块的搜索路径

上面的例子里,我们导入自己写的hello_world模块时提到,须和test.py位于同一个文件夹下。就是说,test.py在import时会在当前目录下查找叫做hello_world.py的文件。

我们可能会有疑问,如果项目做大了必须要分子目录了怎么办?安装第三方模块时是默认安装到了系统目录里,python是如何找到的?又如,如果服务器上安装好几个版本numpy模块库,我们该怎么指定需要的版本?

想搞清楚这些问题,我们就需要先搞清楚python查找模块的规则。我们知道linux在查找可执行命令时是安照PATH环境变量的顺序。类似地,python按照sys.path的顺序来查找模块定义。比如,windows环境下,我们把sys.path打印出来,如下:

import sys
print(sys.path)

输出:
['', 'C:\Python\Python36\python36.zip', 'C:\Python\Python36\DLLs', 'C:\Python\Python36\lib', 'C:\Python\Python36', 'C:\Python\Python36\lib\site-packages']

我们可以看到,sys.path其实是列表,里面存着一个个路径。python按照列表的先后顺序,逐个目录查找,直到找到模块定义。知道了这一点,我们就可以根据需要手工改造sys.path的列表,比如把我们自己写的模块目录insert到sys.path的一开头,比如delete掉某个不需要的目录,比如调换两个目录的顺序,等等。

另外python启动时还会读取PYTHONPATH的环境变量,并insert到sys.path的一开头。因此,我们也可以修改PYTHONPATH来指定需要的模块所在目录。我们需要结合实际,决定是修改PYTHONPATH还是直接修改sys.path。看哪个可行,看哪个更方便。

如何安装模块

如果你的服务器可以联网,那么恭喜你,你只需要一个命令pip install xxx就可以安装第三方模块。pip是python安装第三方模块的工具。比如,如果你需要安装numpy,只需要pip install numpy即可,安装过程中会自动下载安装依赖包。

有些童鞋立即试了试,却发现“没有pip命令”?那很可能是没有安装pip,或者没有正确设置PATH环境变量。

windows环境下,先看看python安装目录下的scripts文件夹里有没有pip.exe。如果有,就添加C:\Python36\Scripts到环境变量。如下图。

py scrits

如果Scripts文件夹里没有pip.exe,就需要安装pip了。在控制面板->添加删除软件的找到python,右键点更改,再勾上pip。如下图。

py reinstall

py reinstall pip

但我们的服务器一般是Linux,如果确认Scripts目录没有pip,就需要去官网下载pip源码包来安装。下载地址:https://pypi.python.org/pypi/pip/9.0.1,找到pip-9.0.1.tar.gz。解压缩后,用命令python setup.py install安装。

但是,但是,有不少童鞋说,“我们服务器不能连网,也没有管理员权限”。不用担心,这种情况下,我们需要下载好numpy源码包和所有的依赖包,手动安装到自己的HOME目录或者指定的目录。

源码包去哪里下载?当然是去python官网,https://pypi.python.org/pypi。那么怎么知道要哪些依赖包呢?不用担心,如果缺少依赖包,安装时会报错。缺什么补什么。

一般来说,安装源码包安装方法是python setup.py install --prefix /home/xxx,其中,--prefix指定安装到自己的HOME目录下,因为我们没有管理员权限。

部分第三方模块,不需要安装,只要解压至一个目录,并加到python的模块搜索路径即可使用。如果遇到某些包实在无法安装,可以试试这种方法。

这里顺便介绍一下,如何安装Tcl和Tk包。一些童鞋在安装matplotlib模块库时,发现python缺少Tk库。分两种情况,如果Linux服务器能联网,且有管理员权限,则优先选用yum install xxx(RHEL、CentOS)或者apt_get install xxx(Ubantu、Debian)。另一种情况就下没联网、没权限,我们下面简单介绍一下源码安装的步骤。

./configure --prefix=/home/xxx(xxx是你的用户名)
make
make test
make install

一般情况下,到这里,你已经可以在python中import tkinter了。但如果你的python也是自己用源码编译安装的话,那很可能你需要重新编译安装python。方法如下:

install tk

阅读数:
更多文章:文章目录
解惑专区
(支持markdown插入源代码)
欢迎使用ExASIC订阅服务
仅用于ExASIC最新文章通知,方便及时阅读。
友情链接: IC技术圈问答ReCclayCrazyFPGA