Python3: 模块 和 包,包管理工具 pip

浅浅的花香味﹌ 2021-09-21 22:42 452阅读 0赞

本文链接: https://blog.csdn.net/xietansheng/article/details/115557530

Python3 学习笔记(目录)

「模块」官方文档: https://docs.python.org/zh-cn/3/tutorial/modules.html

1. 模块

一个 Python 脚本文件(后缀名为.py)就是一个模块,可以直接运行,也可以被其他模块导入并使用其中定义的名称(类、方法、变量)。

1.1 以脚本的方式运行模块

把下面代码保存为文件: demo.py

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. import sys
  4. print("命令行输如的参数:")
  5. # sys.argv 是一个列表, 表示执行脚本文件时
  6. # 传入的参数列表, 首个元素为脚本文件本身
  7. for arg in sys.argv:
  8. print(arg)

demo.py 是一个 Python 脚本文件(源文件),也表示一个 Python 模块,以脚本的方式运行模块:

  1. $ python3 demo.py
  2. demo.py
  3. $ python3 demo.py aa bb 123
  4. demo.py
  5. aa
  6. bb
  7. 123
  8. $ ./demo.py aa bb
  9. ./demo.py
  10. aa
  11. bb

1.2 import、from 和 as 语句

1.2.1 import

在 Python 源文件中引入其他模块,通常在源文件头部执行import语句:

  1. import module1[, module2[, ..., moduleN]]

当解释器遇到 import 语句时,导入指定的模块,并执行该模块文件内的代码,多次(包括在不同模块内)使用 import 导入模块,模块内的代码只执行一次。模块被导入后,其名称便作为变量标识符在当前模块内即被定义,在当前模块内通过模块.名称访问模块内的变量、类 或 函数。

  1. >>> import sys # 导入 sys 模块
  2. >>> sys.path # 通过 模块.名称 访问模块内的资源
  3. ['', ..., .../python3.7/site-packages']

1.2.2 from

使用 from 语句可以导入模块内的部分名称(变量、类 或 函数),语法格式:

  1. from module import [ArgOrClassOrFun1[, ArgOrClassOrFun2[, ..., ArgOrClassOrFunN]]

示例:

  1. >>> from sys import path # 从模块 sys 导入 path 名称
  2. >>> path # path 指向 sys.path
  3. ['', ..., .../python3.7/site-packages']
  4. # PS_1: 导入的只是 sys 模块中的 path 名称, 并在当前以相同的
  5. # 名称创建变量(引用) path 指向 sys.path
  6. # PS_2: sys 并没有被导入, 因此 sys 在当前属于“未定义”。

导入模块内的所有名称:

  1. >>> from sys import * # *号表示导入 sys 模块中的所有名称
  2. >>> path # sys.path
  3. ['', ..., .../python3.7/site-packages']
  4. >>> version # sys.version
  5. '3.7.2 (v3.7.2:9a3ffc0492, Dec 24 2018, 02:44:43)...'
  6. # PS: 导入的 sys 模块的所有名称, 在当前将以相同的名称被逐一定义为变量,
  7. # 导入的仅为 sys 模块中的名称, sys 并没有被导入,
  8. # 因此 sys 在当前属于“未定义”。

1.2.3 as

使用as关键字将导入的名称起另一个名称:

  1. >>> import sys as s
  2. >>> s.path
  3. ['', ..., .../python3.7/site-packages']
  4. # PS: 导入 sys 模块并作为另一个名称 s, s 在当前被定义为一般变量指向 sys 模块,
  5. # 使用 as 起另一个别名 s 后, 当前只能使用别名 s 访问 sys 模块, sys 在当前属于“未定义”。
  6. >>> from sys import path as p
  7. >>> p
  8. ['', ..., .../python3.7/site-packages']
  9. # PS: p 在当前将被定义为一个变量指向 sys.path,
  10. # sys 和 path 在当前都属于“未定义”。

1.3 模块内的 __all__ 变量

通常使用import *语句将导入模块内的所有名称,如果想只导入部分指定的名称,可以在模块内定义了一个__all__变量保存需要导入的名称,其类型为list类型。

一个模块内如果定义了__all__变量,则使用import *语句导入模块的所有名称时,将只导入__all__变量中保存的名称。

示例:

脚本文件demo.py:

  1. # 使用 import * 导入模块名称时, 将只导入 fun1 和 aa
  2. __all__ = ["fun1", "aa"]
  3. def fun1():
  4. print("demo fun1")
  5. def fun2():
  6. print("demo fun2")
  7. aa = 100
  8. bb = "Hello"

访问 demo 模块:

  1. >>> from demo import * # 导入 demo 模块内的名称
  2. >>> fun1() # 正常访问
  3. demo fun1
  4. >>> aa # 正常访问
  5. 100
  6. >>> fun2() # fun2 未定义
  7. NameError: name 'fun2' is not defined
  8. >>> bb # bb 未定义
  9. NameError: name 'bb' is not defined

1.4 模块搜索路径

搜索模块官网介绍: The-module-search-path

当一个名为demo的模块被import时,解释器首先在 内置模块 中查找该模块。如果找不到,则解释器从sys.path变量给出的目录列表中逐一查找出名为demo.py的文件。如果都找不到,则抛出ModuleNotFoundError异常。

1.4.1 sys.path 的初始化值依次如下:

  1. 被执行的脚本文件所在目录(没有指定脚本文件时为当前目录)

    • PYTHONPATH 环境变量指定的目录(添加多个路径使用os.pathsep路径分隔符分隔)
    • 安装 Python 时决定的默认设置(即默认安装的 Python 库所在的相关目录列表)

在初始化后,Python 程序中可以更改sys.path(增加或移除目录)。更改后import查找模块时将从最新的sys.path目录列表中依次查找指定模块。

1.4.2 sys.path 的值示例:

  1. $ export PYTHONPATH="/aa:/bb/cc" # 设置 PYTHONPATH 环境变量(Linux)
  2. $ python3 # 运行 Python 解释器, 没有指定脚本文件
  3. >>> import sys
  4. >>> sys.path
  5. [
  6. '', # 1. 没有指定脚本文件, 则第一个目录为空字符串, 即表示当前目录
  7. '/aa', # 2. 从 PYTHONPATH 环境变量中获取的路径
  8. '/bb/cc', # 2. 从 PYTHONPATH 环境变量中获取的路径
  9. '.../lib/python37.zip', # 3. 以下的为其他默认路径(省略前缀)
  10. '.../lib/python3.7',
  11. '.../lib/python3.7/lib-dynload',
  12. '.../lib/python3.7/site-packages'
  13. ]

1.4.3 运行脚本文件时 sys.path 的值示例:

脚本文件:/aa/bb/demo.py

  1. import sys
  2. print(sys.path)

运行脚本文件:

  1. $ python3 /aa/bb/demo.py # 运行指定的脚本文件
  2. [
  3. '/aa/bb', # 有指定脚本文件, 则第一个目录为脚本文件所在目录
  4. '.../lib/python37.zip',
  5. '.../lib/python3.7',
  6. '.../lib/python3.7/lib-dynload',
  7. '.../lib/python3.7/site-packages'
  8. ]

1.5 模块内的 __name__ 属性

模块内有一个 __name__ 属性,表示模块的名称。模块可以被其他模块导入执行,也可以自身执行。
当模块被其他模块导入执行时,__name__ 属性的值为模块的名称;当模块自身被执行时,__name__ 属性的值为 "__main__"

脚本文件 demo.py:

  1. if __name__ == "__main__":
  2. print("模块自身执行")
  3. else:
  4. print("被其他模块导入执行")

访问 demo 模块:

  1. $ python3 demo.py
  2. 模块自身执行
  3. $ python3
  4. >>> import demo
  5. 被其他模块导入执行

通过__name__属性可以判断当前模块是否为自身被执行,因此可以在 Python 程序的启动脚本文件内定义一个main函数作为程序的主函数入口,并通过判断是否为自身被执行来运行主函数,如下:

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. def main():
  4. print("主函数被执行")
  5. if __name__ == "__main__":
  6. main()

1.6 标准模块(库)

Python 安装时附带了一个标准模块库: https://docs.python.org/zh-cn/3/library/index.html

一些模块内置于解释器中,它们不属于语言核心内容,只是为了提高的效率或提供系统调用等操作系统原生的访问。例如winreg模块只在 Windows 操作系统上才提供。一个需要特别注意的模块sys,它被内嵌到每一个 Python 解释器中,其中变量sys.ps1sys.ps2定义了交互模式下的主要和辅助提示字符串:

  1. >>> import sys
  2. >>> sys.ps1
  3. '>>> '
  4. >>> sys.ps2
  5. '... '
  6. >>> sys.ps1 = "$ "
  7. $ print("Hello")
  8. Hello
  9. $ sys.ps2 = "*** "
  10. $ 1 + 2 \
  11. *** + 3
  12. 6
  13. $

sys.ps1sys.ps2 这两个变量只在 交互模式 下运行解释器时才被定义,脚本文件中访问这两个变量将抛出 AttributeError 异常。

1.7 第三方模块(库)

Python 第三方库获取: https://pypi.org

除了内置的一些标准模块库,还有许多第三方发布的各类模块库,可以下载下来安装到本地,或通过pip命令在线安装(见后面的 pip 命令介绍)。

1.8 dir() 函数

内置函数dir(p_object=None)可用于查找一个模块内定义的有效名称(变量、函数、类、模块等)列表,返回一个字符串列表:

  1. >>> import sys
  2. >>> dir(sys) # 列出 sys 模块内的名称(结果太多, 省略部分)
  3. [
  4. '__doc__', '__name__', '__package__',
  5. '__stderr__', '__stdin__', '__stdout__',
  6. ...
  7. 'api_version', 'argv',
  8. 'stderr', 'stdin', 'stdout',
  9. 'thread_info', 'version', 'version_info'
  10. ]
  11. >>> sys.version
  12. '3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 16:52:21) \n[Clang 6.0 (clang-600.0.57)]'
  13. # PS: dir() 函数不会列出内置函数和变量的名称。

实际上 dir 函数的 p_object 参数接收的是一个对象, 可以是任意对象,在 Python 中一切皆是对象,因此 dir 函数可以查找任意对象所拥有的有效名称(变量、函数、类、模块等)列表,示例:

  1. >>> s = "hello" # 定义一个字符串
  2. >>> dir(s) # 列出字符串对象 s 所拥有的名称(结果太多, 省略部分)
  3. [
  4. '__add__', '__dir__', '__doc__', '__len__',
  5. 'find', 'index', 'lower', 'lstrip', 'replace',
  6. ...
  7. 'rfind', 'rindex', 'strip', 'upper'
  8. ]
  9. >>> s.upper()
  10. 'HELLO'
  11. >>> dir() # 不传参数(即默认传 None), 输出的是当前作用域中的名称列表
  12. ['__builtins__', '__doc__', '__name__', '__package__', 's']
  13. >> dir(dir) # dir 函数本身也是一个对象, 也可以查找 dir 所拥有的名称列表
  14. ...

2. 包

「包」的官网介绍: Packages

2.1 包的简介

包是一种管理 Python 模块命名空间的方法,通过包名.模块名的方式表示具体模块。例如,模块A.B表示A包中名为B的子模块,模块A.B.C表示A.B包中名为C的子模块。有了包名做前缀,不同模块的作者就不必担心彼此的模块名称重复。

包在文件系统中以文件夹的形式存在,多级包A.B.C以文件夹目录(A/B/C)的形式表示。作为包的文件夹内必须要有__init__.py文件才能让 Python 把包含该文件的目录当做包。__init__.py文件可以使一个空文件,也可以在其中添加包的初始化代码或设置__all__变量。

有了包结构对模块的管理,一个复杂的模块库就可以把其中不同功能的模块细分到不同的子包中,使得更容易对代码功能的细致管理和使用,而且也不需要担心模块名称的重复问题。下面是官网给出的假设处理声音文件和数据的模块库的可能的包结构:

  1. sound/ # 顶层包(文件夹)
  2. __init__.py # 顶层包的初始化脚本文件
  3. formats/ # 用于文件格式转换的子包(文件夹)
  4. __init__.py # 子包的初始脚本文件
  5. wavread.py # 包内的具体模块的脚本文件
  6. wavwrite.py
  7. aiffread.py
  8. aiffwrite.py
  9. auread.py
  10. auwrite.py
  11. ...
  12. effects/ # 处理声音效果的子包
  13. __init__.py
  14. echo.py
  15. surround.py
  16. reverse.py
  17. ...
  18. filters/ # 过滤器子包
  19. __init__.py
  20. equalizer.py
  21. vocoder.py
  22. karaoke.py
  23. ...

import一个包中的模块sound.formats.wavread时,Python 解释器将从sys.path列表的目录下逐一搜索出路径为sound/formats/wavread.py的文件。因此顶层包必须在sys.path目录列表中的其中一个目录下,否则将抛出ModuleNotFoundError的异常。

TODO: 包模块中的变量 __name__, __path__, __package__

2.2 包中模块的导入

通过全名导入具体模块:

  1. import sound.formats.wavread # 直接通过全名导入模块
  2. sound.formats.wavread.fun(...) # 上面的导入方法, 引用时必须使用全名
  3. # 假设 fun 是模块 wavread 中的一个函数

通过全名导入具体模块,并为模块起一个新的别名:

  1. import sound.formats.wavread as wr # 直接通过全名导入模块
  2. wr.fun(...) # 通过别名引用

从具体模块中导入一个函数:

  1. from sound.formats.wavread import fun # 导入具体模块中的一个函数
  2. fun(...) # 直接使用导入的函数名

从包中导入模块:

  1. from sound.formats import wavread # 从包 sound.formats 中导入模块 wavread
  2. wavread.fun(...) # 上面的导入方法, 引用模块时只需要使用 wavread

从包中导入所有模块:

  1. from sound.formats import * # 从包 sound.formats 中导入模块所有模块
  2. wavread.fun1(...) # 导入后, 包中的所有模块在当前都可直接引用
  3. wavwrite.fun2(...)

2.3 __init__.py 与 __all__

每个 Python 包文件夹下都有一个__init__.py脚本文件,用于表示该文件夹是一个 Python 包。__init__.py脚本文件在其包被引用时将被执行,即只要在 Python 代码中的 import 或 from 语句中涉及了该包,则即会被执行(多次引用包只执行一次)。

__all__变量是一个字符串列表,__init__.py脚本文件中如果定义了__all__变量,则通过from package import *的方式导入包内模块时,只会导入__all__列表中定义的模块名称。

例如,脚本文件: sound/formats/__init__.py

  1. __all__ = ["wavread", "wavwrite"]

在代码中导入模块:

  1. # 只会导入 wavread.py 和 wavwritep.py 模块
  2. from sound.formats import *

2.4 脚本中的变量: __name__、__path__、__package__

在包文件夹下的 __init__.py 初始脚本文件中:

  • __name__: 表示 __init__.py 所在包的名称。
  • __package__: 表示 __init__.py 所在包的名称。
  • __path__: 表示 __init__.py 所在包的路径,格式为字符串列表类型。

在普通的脚本文件中:

  • __name__: 非模块自身运行时,表示脚本文件对应的模块全名(包括包名前缀)。
  • __package__: 表示脚本文件所在包的名称(没有包名是为 None)。
  • __path__: 在脚本文件中无定义。

3. 模块的打包与安装

3.1 打包模块

(1) 一个名称为 MyModule 的模块目录结构:

  1. . # MyModule 目录
  2. |--- steup.py # 模块的配置文件
  3. |--- toppkg # 顶层包
  4. |--- suba # 子包
  5. | |--- aa.py # 脚本文件
  6. | |--- bb.py # 脚本文件
  7. | |--- __init__.py
  8. |--- subb # 子包
  9. | |--- cc.py # 脚本文件
  10. | |--- dd.py # 脚本文件
  11. | |--- __init__.py
  12. |--- __init__.py

(2) 编辑 steup.py 配置文件:

  1. from distutils.core import setup
  2. setup(name="MyModule", # 模块名称
  3. version="1.0", # 模块版本
  4. description="my custom module", # 模块描述
  5. author="Me", # 模块作者
  6. author_email="xxxx@qq.com", # 作者邮箱
  7. py_modules=["toppkg.suba.aa", # 此模块包所包含的所有模块(py脚本文件)
  8. "toppkg.suba.bb",
  9. "toppkg.subb.cc",
  10. "toppkg.subb.dd"])

(3) 构建模块

运行 setup.py 脚本,构建模块: python3 setup.py build

构建成功后生成一个 build 目录:

  1. . # MyModule 目录
  2. |--- build # 构建生产的 build 目录
  3. | |--- lib
  4. | |--- toppkg
  5. | |--- suba
  6. | | |--- aa.py
  7. | | |--- bb.py
  8. | | |--- __init__.py
  9. | |--- subb
  10. | |--- cc.py
  11. | |--- dd.py
  12. | |--- __init__.py
  13. |--- steup.py
  14. |--- toppkg
  15. |--- suba
  16. | |--- aa.py
  17. | |--- bb.py
  18. | |--- __init__.py
  19. |--- subb
  20. | |--- cc.py
  21. | |--- dd.py
  22. | |--- __init__.py
  23. |--- __init__.py

(4) 打包模块

运行 setup.py 脚本,打包模块: python3 setup.py sdist

打包成功后,生成一个 MyModule-1.0.tar.gz 压缩包:

  1. . # MyModule 目录
  2. |--- build
  3. | |--- lib
  4. | |--- toppkg
  5. | |--- suba
  6. | | |--- aa.py
  7. | | |--- bb.py
  8. | | |--- __init__.py
  9. | |--- subb
  10. | |--- cc.py
  11. | |--- dd.py
  12. | |--- __init__.py
  13. |--- dist
  14. | |--- MyModule-1.0.tar.gz # 打包生成的压缩包
  15. |--- steup.py
  16. |--- toppkg
  17. |--- suba
  18. | |--- aa.py
  19. | |--- bb.py
  20. | |--- __init__.py
  21. |--- subb
  22. | |--- cc.py
  23. | |--- dd.py
  24. | |--- __init__.py
  25. |--- __init__.py

MyModule-1.0.tar.gz 压缩包即为 最终可发布 的模块包,其内部目录结构为:

  1. MyModule-1.0.tar.gz
  2. |--- MyModule-1.0 # 压缩包内顶层文件夹
  3. |--- setup.py # 配置文件
  4. |--- PKG-INFO # 包的信息文件
  5. |--- toppkg # 源码包
  6. |--- suba
  7. | |--- aa.py
  8. | |--- bb.py
  9. | |--- __init__.py
  10. |--- subb
  11. | |--- cc.py
  12. | |--- dd.py
  13. | |--- __init__.py
  14. |--- __init__.py

3.2 模块安装

(1) 获取到模块安装包MyModule-1.0.tar.gz,解压得到文件夹MyModule-1.0:

  1. MyModule-1.0
  2. |--- setup.py
  3. |--- PKG-INFO
  4. |--- toppkg
  5. |--- suba
  6. | |--- aa.py
  7. | |--- bb.py
  8. | |--- __init__.py
  9. |--- subb
  10. | |--- cc.py
  11. | |--- dd.py
  12. | |--- __init__.py
  13. |--- __init__.py

(2) 安装模块包

  1. # 先进入解压后的模块文件夹
  2. cd MyModule-1.0
  3. # 执行 setup.py 脚本安装
  4. python3 setup.py install
  5. # 默认把模块安装到 Python 安装目录下的 site-packages 文件夹下

指定安装目录:

  1. python3 setup.py install --prefix=安装目录
  2. # 执行完后, 模块将安装到: {安装目录}/lib/site-packages

(3) 引用模块

安装完后,确保安装路径在sys.path目录列表中,在 Python 代码中即可直接导入使用:

  1. from toppkg.suba import aa

4. 包管理工具: pip

安装 Python 模块官网介绍: https://docs.python.org/zh-cn/3/installing/index.html

4.1 pip 简介

pip是管理 Python 模块的工具,本身也是一个 Python 模块。从 Python 3.4 开始默认包含在 Python 的二进制安装程序中。

Python Packaging Index(PyPI)是一个由 Python 开发者向其他用户发布开源许可软件包的公共仓库,使用pip命令可以从其中在线搜索安装想要的 Python 软件包(模块库)。

pip 相关网站:

  • pip GitHub 仓库: https://github.com/pypa/pip
  • pip 项目介绍: https://pypi.org/project/pip/
  • pip 安装介绍: https://pip.pypa.io/en/stable/installing/
  • pip 使用说明: https://pip.pypa.io/en/stable/
  • pip 命令行: https://pip.pypa.io/en/latest/cli/

如果没有安装 pip 模块,可以手动安装:

  • pip 安装文件下载: https://pypi.org/project/pip/#files

或者使用get-pip.py文件安装:

  1. $ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
  2. $ python3 get-pip.py

升级 pip 的版本:

  1. # 升级 pip 版本, 需要使用 python 的命令来升级
  2. python3 -m pip install --upgrade pip

4.2 pip 命令

pip 安装软件包命令相关官网链接:

  • Installing Packages
  • Installing from PyPI
  • Upgrading packages

4.2.1 安装软件包

  1. pip3 install PackageName # 普通安装(在线安装)
  2. pip3 install whl_package_file.whl # 离线安装, 先下载好 whl 安装文件再安装
  3. pip3 install --upgrade PackageName # 升级软件包
  4. pip3 install "PackageName==1.0.4" # 指定特定版本
  5. pip3 install "PackageName>=1.0.4" # 指定最小版本
  6. pip3 search PackageNameKeyword # 从 PyPI.ORG 在线搜索软件包
  7. pip3 download PackageName # 下载软件包(默认下载到当前目录)
  8. pip3 check PackageName # 校验已安装的软件包是否已具有兼容的依赖

4.2.2 卸载软件包

  1. pip3 uninstall PackageName

4.2.3 查看软件包

  1. pip3 list # 列出已安装的所有软件包
  2. pip3 freeze # 以必需的格式列出已安装的软件包
  3. pip3 show [--files] PackageName # 查看某个软件包的详细信息

4.2.4 pip 命令帮助

  1. $ pip3 --help
  2. Usage:
  3. pip3 <command> [options]
  4. or
  5. python3 -m pip <command> [options]
  6. Commands:
  7. install Install packages.
  8. download Download packages.
  9. uninstall Uninstall packages.
  10. freeze Output installed packages in requirements format.
  11. list List installed packages.
  12. show Show information about installed packages.
  13. check Verify installed packages have compatible dependencies.
  14. config Manage local and global configuration.
  15. search Search PyPI for packages.
  16. wheel Build wheels from your requirements.
  17. hash Compute hashes of package archives.
  18. completion A helper command used for command completion.
  19. help Show help for commands.
  20. General Options:
  21. -h, --help Show help.
  22. --isolated Run pip in an isolated mode, ignoring
  23. environment variables and user configuration.
  24. -v, --verbose Give more output. Option is additive, and can be
  25. used up to 3 times.
  26. -V, --version Show version and exit.
  27. -q, --quiet Give less output. Option is additive, and can be
  28. used up to 3 times (corresponding to WARNING,
  29. ERROR, and CRITICAL logging levels).
  30. --log <path> Path to a verbose appending log.
  31. --proxy <proxy> Specify a proxy in the form
  32. [user:passwd@]proxy.server:port.
  33. --retries <retries> Maximum number of retries each connection should
  34. attempt (default 5 times).
  35. --timeout <sec> Set the socket timeout (default 15 seconds).
  36. --exists-action <action> Default action when a path already exists:
  37. (s)witch, (i)gnore, (w)ipe, (b)ackup, (a)bort).
  38. --trusted-host <hostname> Mark this host as trusted, even though it does
  39. not have valid or any HTTPS.
  40. --cert <path> Path to alternate CA bundle.
  41. --client-cert <path> Path to SSL client certificate, a single file
  42. containing the private key and the certificate
  43. in PEM format.
  44. --cache-dir <dir> Store the cache data in <dir>.
  45. --no-cache-dir Disable the cache.
  46. --disable-pip-version-check
  47. Don't periodically check PyPI to determine
  48. whether a new version of pip is available for
  49. download. Implied with --no-index.
  50. --no-color Suppress colored output

发表评论

表情:
评论列表 (有 0 条评论,452人围观)

还没有评论,来说两句吧...

相关阅读