一、模块

.py 文件就称为一个模块(module)。为避免模块名冲突,Python引入了按目录来组织模块的方法,称为包(package)。

       使用模块优点:①提高代码可维护性 ②编写代码不必从零开始,当一个模块编写完毕,就可以被其他地方引用。③避免函数名和变量名冲突,相同名字的函数和变量完全可以分别存在不同的模块中。

       说了半天,到底什么是模块?什么是包?举个简单例子一目了然:

mycompany
├─ __init__.py
├─ abc.py
└─ xyz.py
其中,mycompany就是顶层包名,abc.py文件是一个名字叫abc的模块,xyz.py文件是一个名字叫xyz的模块。
引入包以后,只要顶层包名不发生命名冲突,其下所有模块都不会与别的模块发生冲突。在这里abc.py模块的名字变为mycompany.abc,同样的xyz.py模块名变为mycompany.xyz.
细心的同学还会发现,每一个包目录下面都会有一个__init__.py文件,这个文件是必须存在的,否则,Python机会把这个目录当成普通目录,而不是一个包。__init__.py可以是空文件,也可以有Python代码,因为__init__.py本身就是一个模块,而它的模块名为mycompany.

       类似的,还有多级目录,组成多层次的包结构。如下面的目录结构:

mycompany
 ├─ web
 │  ├─ __init__.py
 │  ├─ utils.py
 │  └─ xyz.py
 ├─ __init__.py
 ├─ abc.py
 └─ utils.py
这里文件xyz.py的模块名为mycompany.web.xyz,而两个utils.py的模块名分别为mycompany.utils和mycompany.web.utils。

注:a、模块是一组Python代码的集合,可以使用其他模块,也可以被其他模块使用。

        b、创建自己模块时要注意:模块名要遵循Python变量命名规范,不使用中文、特殊字符;模块名不要和系统中模块名冲突,最好先查看系统是否已经存在该模块,检查方法是在Python交互环境执行import xxx,若成功则说明系统存在此模块。

二、不同目录下导入模块

       1.同级目录下的调用

       目录结构如下:

mycompany
 ├─ model1.py
 └─ model2.py

import model1 或 from model1 import xxx(from model1 import *);

       2.调用子目录下的模块

       目录结构如下:

mycompany
 ├─ web
 │  ├─ abc.py
 │  └─ xyz.py
 ├─ model1.py
 └─ model2.py

       若在程序model1.py中导入模块abc.py,可以在web文件夹中建立空文件夹__init__.py文件。新目录结构如下:

mycompany
 ├─ web
 │  ├─ abc.py
 │  |_ xyz.py
 |  |_ __init__.py
 ├─ model1.py
 └─ model2.py

from web.abc import xxx 或者 import web.abc (输出需要print(web.abc.xxx(参数)))

       3.调用上级目录下的文件

       目录结构如下:

mycompany
 ├─ web
 │  ├─ abc.py
 │  |_ xyz.py
 |  |_ __init__.py
 |
 |——lib
 |  |_ test1.py
 |
 ├─ model1.py
 └─ model2.py

       若程序test1.py中导入abc.py 和 model1.py,做法是先跳到mycompany目录下面,直接可以调用model1.py,然后在web下建立一个空文件__init__.py,这个文件我们上一步已经建过了,建好以后就可以像第2步调用子目录下模块一样,通过import web.abc 进行调用。具体代码如下:

import sys
sys.path.append("E:\\PythonWorkspace\\mycompany") #这里是我的mycompany文件路径
import model1
import web.abc
注:打印输出print(model1.方法名(参数))
           print(web.abc.方法名(参数))
    特别注意:sys.path.append()添加路径时注意是在Windows还是在Linux下,Windows下需要'\\'否则会报错

        细心的童鞋可以发现,其实上述代码有一个缺点,sys.path.append("E:\\PythonWorkspace\\mycompany")这句是写死的。自己的代码拷到别人的机器上依然会出错,那怎么办?重新改这条路径?不是不可以,但有没有更好的方法,答案当然是“有”!我们把这条路径写为相对路径不就可以了,聪明~~~~

import os
import sys
'''
print(__file__)#获取当前程序路径,注意:这里打印出来的路径为相对路径
#动态获取绝对路径
print(os.path.abspath(__file__)) #这才是当前程序绝对路径
print(os.path.dirname(os.path.abspath(__file__))) #当前程序上一级目录,其中dirname返回目录名,不要文件名
print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))#当前程序上上一级目录
'''
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #当前程序上上一级目录,这里为mycompany
sys.path.append(BASE_DIR) #添加环境变量

import model1
import web.abc

 

       关于__init__.py

__init__.py文件(这个文件定义了包的属性和方法),然后是一些模块文件和子目录,假如子目录中也有__init__.py那么它就是这个包的子包。当我们将一个包作为模块导入(比如从xml导入dom)的时候,实际上导入了它的__init__.py文件。

       一个包是一个带有特殊文件__init__.py的目录。__init__.py文件定义了包的属性和方法,其实它可以什么也不定义,即只是一个空文件,但是必须存在。如果__init__.py这个文件不存在,这个目录就仅仅是一个普通目录,而不是一个包,它就不能被导入或者包含其他的模块和嵌套包。

__init__.py文件,它可以是空文件,也可以写包初始化相关代码,或者定义 __all__ 变量。__all__变量是一个列表,它列举了这个包包含的子模块名称。如果此时目录如下:

mycompany
 ├─ web
 │  ├─ abc.py
 │  |_ xyz.py
 |  |_ __init__.py
 |  |_ demo
 |      |_ demo.py
 |
 |——lib
 |  |_ test1.py
 |
 ├─ model1.py
 └─ model2.py

       当我们使用全部导入,也就是 from web import *(通常不主张这样做,会导致代码可读性降低,而且如果我们自己命名和模块里面的名称一样,就会覆盖模块里面的名字) ,实际上会把这个模块名称列表里面的模块名称导入,如下:。如果觉得从包中导入 * 的操作没有必要,也可以不定义__all__这个变量。但是在更新包之后__all__也需要更新。

#__init__.py文件
__all__ = ["abc","xyz","demo"]

       4.安装第三方模块

#方法一:pip安装
电脑如果有多个版本的Python时,pip3可以自动判别用Python3来安装库,是为了避免与Python2发生冲突。
如果电脑仅仅安装了Python3,那么使用pip或者pip3是一样的。

pip install xxx
新安装的第三方库会放到这个目录下面:Python2.7/site-packages
pip3 install xxx
新安装的第三方库会放到这个目录下面:Python3.6/site-packages 

#方法二:Anaconda安装(推荐)
conda install xxx