基本概念

  • 模块:将一组功能相关的代码写入一个单独的.py文件中,需要时进行导入,这个文件就是模块。
  • :有层次的文件目录结构,内部有多个模块多个子包,一般要有__init__.py这个文件(3.3+ 的版本不需要)。
  • :完成一定功能代码的集合,完成的功能一般更加广泛,可以是模块,也可以是包。
  • 框架:通过框架,可以快速实现解决某一个问题所需的代码骨架,后期进行填充即可。

    包和模块的作用

  • 轮子,工具代码,供其他模块使用(模块化编程)

  • 划分了变量作用域,解决变量/函数重名的问题

    包和模块分类

  • 内建的模块:builtin,会自动导入。

  • 第三方包/模块:由其他人员开发,需要下载安装才能使用。
  • 自定义包/模块:自己写的。

    包和模块的一般操作

    创建模块

    ```python

    就是创建一个 .py文件

    n1 = 1 n2 = 2 n3 = 3 def test(): pass

all = [“n1”, “n2”, “test”] # 指定了可以导入到别的模块中的资源

  1. <a name="3b424b13"></a>
  2. ## 创建包
  3. - 新建一个文件夹,为了兼容,添加一个`__init__.py`文件(当包被导入时,会运行这个文件)。
  4. - 在文件中设置`__all__`变量,可以限制能够通过`from package import *`所导出的模块。
  5. <a name="c3f6be32"></a>
  6. ## 包和模块的导入
  7. ```python
  8. """
  9. 1.常规导入,导入了所有资源
  10. """
  11. import module
  12. module.val # 访问变量
  13. module.func() # 调用函数
  14. # 模块在其他的包中
  15. import p.module
  16. p.module.val
  17. # 一次导入多个模块
  18. import p.module, module, module_2
  19. # 给模块起别名
  20. import p.module as m
  21. m.val
  22. m.func()
  23. """
  24. 2.from语句导入,只导入部分资源
  25. """
  26. # 从包中导入模块
  27. from p import module
  28. module.val
  29. from p import module1, module2
  30. from p import module1 as m1, module2 as m2
  31. from p.sub_p import m # 正确写法
  32. from p import sub_p.m # 错误写法
  33. # 从模块中导入资源
  34. from module import val, func
  35. print(val) # 直接使用
  36. func()
  37. from p.mudule import val # True
  38. from p import module.val # False
  39. from p import * # 导入了 p包下的所有模块,受到 __init__.py文件中__all__变量的约束
  40. from module import * # 导入了 module下的所有资源,受到模块中 __all__变量的约束
  41. # 使用 * 进行导入,容易产生同名冲突

导入操作的本质

  • 第一次导入
    • 被导入的模块会在自己的命名空间中执行所有的代码。
    • 代码执行完成后,会产生一个模块对象,模块中的所有属性都绑定到这个对象上,对象的名称就是模块名。
    • 目标模块在import位置建立引用,就可以根据模块对象的名称来访问资源了。
  • 第二次导入
    • 直接建立到对象的引用,也就是第一次导入的第三步。
  • 两种导入方式都会执行模块的所有代码,所以不存在第二种方式更省内存的说法,只是拿不同的部分来使用。

    模块检索路径

  • 检索模块按照一定的顺序进行,优先在具有较高优先级的地方查找。

  • 先在内置模块中查找,若自己定义了一个和内置模块重名的模块,进行导入时,会导入内置的那个模块。
  • 然后在sys.path(是一个路径列表)中查找
    • 当前目录
    • 环境变量PYTHONPATH
    • 特定路径下的.pth文件所指定的路径
    • python安装目录下的lib
  • 追加路径的方式 (在sys.path增加自定义的路径)

    1. # 直接修改 sys.path
    2. import sys
    3. sys.path.append("xx/xx/xx") # 添加自定义的一个路径,单次执行有效
    4. import xxx # xxx是位于自定义路径下的一个模块
    5. # 直接修改 PYTHONPATH, 因为 sys.path包括了 PYTHONPATH
    6. # 在 shell中有效,在 IDE中又要另外添加
    7. # 作用持久

    导入模块的场景

    局部导入

    1. # 在需要使用的范围内进行导入,其他范围无法使用,多用于函数
    2. def cal(r):
    3. import math
    4. return math.pi * r * r
    5. erea = cal(2)

    覆盖导入

  • 自定义的模块名称和非内置的标准模块重名,根据优先级,前者会覆盖后者

  • 自定义的模块和内置模块重名,后者覆盖前者

    循环导入

  • A模块导入了 B模块,B模块又导入了 A模块

  • 会造成一些问题

    可选导入

    ```python

    对于两个功能相似的模块,想优先导入其中一个,若不存在,再导入另外一个

    try: import module_1 as m except ModuleNotFoundError: import module_2 as m

m.func()

  1. <a name="95834f31"></a>
  2. ## 加载.py文件的两种方式
  3. <a name="154a1bbf"></a>
  4. ### 以脚本形式直接执行
  5. 当一个含有导入模块操作的个文件被执行后,会将自身所在的路径添加到`sys.path`,后面的所有导入(**在当前文件的其他导入 + 所导入模块中的其他导入**)都会参照这个`sys.path`。同时,该文件有一个属性:`__name__ = '__main__'`
  6. <a name="80663391"></a>
  7. ### 作为模块被其他文件导入
  8. 此时其`__name__`属性是由该模块的加载路径所决定的。这个路径作为相对导入时的路径参照。
  9. <a name="d9d6e7b1"></a>
  10. ## 绝对导入和相对导入
  11. ```python
  12. # 绝对导入
  13. # 参照sys.path路径进行模块检索的导入方式
  14. import module
  15. from module import func
  16. # 相对导入
  17. # 用 . 和 .. 来代替绝对路径进行模块的检索
  18. from . import module # 参考的路径是该模块被绝对导入时加载的路径

第三方包和模块的安装

包管理项目

  • distutils
    标准库的一部分,能处理简单的包安装,通过setup.py进行安装
  • setuptools
    现在的包安装标准,使用pip安装脚本,使用whl格式

    三方包和模块的发布形式

  • 源代码
    一个压缩包,解压后里面有setup.py文件,运行即可完成安装

  • .egg
    setuptools引入的一种格式,压缩包,通过安装脚本easy_install进行安装
  • .whl
    为了替代.egg,压缩包,使用pip进行安装

    安装方式

    本地安装

  • 单文件模块
    直接拷贝到sys.path中包含的路径即可,一般放在Lib/site-packages/

  • 带有setup.py文件
    直接使用命令进行安装2.xpython2 setup.py install3.xpython3 setup.py install,注意执行命令时的所在目录即可。
  • .egg文件的安装,使用setuptools的自带安装脚本easy_install进行安装,前提要先安装好easy_install安装命令easy_install xxx.egg
  • .whl文件的安装,推荐使用pip安装。首先要安装pip,一般会自动装上(若没有装,使用easy_install 进行远程安装)。安装命令pip install xxx.whl

    远程安装

  • 自动地从远程下载地址进行检索、下载、安装

  • easy_install xxx
  • pip install xxx
  • 默认安装在Lib/site_packages/
  • 默认是从官网上下载,建议更换安装源。

    安装源(镜像地址)

  • python版本的切换安装

    • easy_install-2.7 xxx
    • easy_install-3.6 xxx
  • 安装指定版本的包
    • 默认是安装最新的版本
    • easy_install "requests >= 2.14.1" 安装大于或等于2.14.1版本的最新包
    • easy_install "requests > 1.0, < 2.0" 安装大于1.0且小于2.0的包
    • easy_install "requests == 2.14.1" 安装当前版本的包,若已经安装,则切换到这个版本
  • 升级第三方包
    • easy_install --upgrade requests
  • 卸载第三方包

    • 手动卸载:1.删除在easy_install.pth中的包记录,2.删除对应的包文件。
    • 命令卸载:easy_install -m requests,并不是真正地卸载了库,相当于执行手动卸载的第一步
    • 对于命令卸载,以后还可以继续使用这个包,只不过不能直接使用python import pkg_resources pkg_resources.require("requires==2.18.4") # 指明你需要的版本 import requests
  • 修改安装源

    • setuptools/command/easy_install.py在里面修改安装源即可

      pip

  • 修改安装源(Windows)

    • 在用户名下创建pip目录,在目录中创建pip.ini文件。C:\Users\xx\pip\pip.ini
    • 编辑文件内容如下:python [global] index-url = http://pypi.douban.com/simple/ trusted-host = pypi.douban.com
  • 修改安装源(Linux)

    • 在用户名下创建.pip目录,目录下创建pip.conf文件。/home/xxx/.pip/pip.conf
    • 文件中的内容和上面相同
  • python版本安装
    • python -m pip install requests
    • python3 -m pip install requests
  • 查看包:pip list
  • 安装指定版本包:pip install "requests >= 1.14.1"
  • 升级包:pip install -- upgrade requests
  • 安装多个版本的库,会以最后一次安装的为准,覆盖安装。若再次执行pip install requests,会给出包已经存在的提示。
  • 卸载包:pip uninstall requests,会删除包文件。
  • 生成冻结需求文本:将当前安装的第三方包记录,储存到指定的文件中,以后,就可以根据这个需求去安装三方包。python pip freeze > ./requirements.txt pip install -r requirements.txt

pip在linux下的一些问题

  • linux默认安装了两个版本的python,我的系统是Ubuntu 16.04,有python 2.7python 3.5两个版本
  • 在家目录下,还会出现.local这个目录,里面记录了pip和用其安装模块的一些信息。这个是面向用户安装的,只在自己的家目录下才有的。
  • 直接使用pip命令,会将安装的包装在python2.7的路径下,有如下对应关系:pip—->python2.7,pip3—->python3.5
  • 使用pip show xxx会显示安装模块的信息``` pip3 show pygame

Name: pygame Version: 1.9.4 Summary: Python Game Development Home-page: https://www.pygame.org Author: Pete Shinners, Rene Dudfield, Marcus von Appen, Bob Pendleton, others… Author-email: pygame@seul.org License: LGPL Location: /home/tc/.local/lib/python3.5/site-packages Requires: Required-by:

  1. - 为了不出什么幺蛾子,以后最好都用下面的方式去定位不同版本的`pip`,简单使用`pip`快捷方式使得其背后指向的解释器版本不明确,如果安装了多个`Python3`版本的解释器,直接使用 `pip` 操作会更加麻烦。`windows``linux`的用法而且不相同,`linux` 下又分为**面向系统**和**面向用户**安装……

都是操作系统级别的包,不会装在自己的家目录下,管理更加方便

python -m pip //for 2.x python3 -m pip //for 3.x pythonx.x -m pip //for x.x ```