Python3: 模块 和 包,包管理工具 pip
本文链接: 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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
print("命令行输如的参数:")
# sys.argv 是一个列表, 表示执行脚本文件时
# 传入的参数列表, 首个元素为脚本文件本身
for arg in sys.argv:
print(arg)
demo.py 是一个 Python 脚本文件(源文件),也表示一个 Python 模块,以脚本的方式运行模块:
$ python3 demo.py
demo.py
$ python3 demo.py aa bb 123
demo.py
aa
bb
123
$ ./demo.py aa bb
./demo.py
aa
bb
1.2 import、from 和 as 语句
1.2.1 import
在 Python 源文件中引入其他模块,通常在源文件头部执行import
语句:
import module1[, module2[, ..., moduleN]]
当解释器遇到 import 语句时,导入指定的模块,并执行该模块文件内的代码,多次(包括在不同模块内)使用 import 导入模块,模块内的代码只执行一次。模块被导入后,其名称便作为变量标识符在当前模块内即被定义,在当前模块内通过模块.名称
访问模块内的变量、类 或 函数。
>>> import sys # 导入 sys 模块
>>> sys.path # 通过 模块.名称 访问模块内的资源
['', ..., .../python3.7/site-packages']
1.2.2 from
使用 from
语句可以导入模块内的部分名称(变量、类 或 函数),语法格式:
from module import [ArgOrClassOrFun1[, ArgOrClassOrFun2[, ..., ArgOrClassOrFunN]]
示例:
>>> from sys import path # 从模块 sys 导入 path 名称
>>> path # path 指向 sys.path
['', ..., .../python3.7/site-packages']
# PS_1: 导入的只是 sys 模块中的 path 名称, 并在当前以相同的
# 名称创建变量(引用) path 指向 sys.path
# PS_2: sys 并没有被导入, 因此 sys 在当前属于“未定义”。
导入模块内的所有名称:
>>> from sys import * # *号表示导入 sys 模块中的所有名称
>>> path # sys.path
['', ..., .../python3.7/site-packages']
>>> version # sys.version
'3.7.2 (v3.7.2:9a3ffc0492, Dec 24 2018, 02:44:43)...'
# PS: 导入的 sys 模块的所有名称, 在当前将以相同的名称被逐一定义为变量,
# 导入的仅为 sys 模块中的名称, sys 并没有被导入,
# 因此 sys 在当前属于“未定义”。
1.2.3 as
使用as
关键字将导入的名称起另一个名称:
>>> import sys as s
>>> s.path
['', ..., .../python3.7/site-packages']
# PS: 导入 sys 模块并作为另一个名称 s, s 在当前被定义为一般变量指向 sys 模块,
# 使用 as 起另一个别名 s 后, 当前只能使用别名 s 访问 sys 模块, sys 在当前属于“未定义”。
>>> from sys import path as p
>>> p
['', ..., .../python3.7/site-packages']
# PS: p 在当前将被定义为一个变量指向 sys.path,
# sys 和 path 在当前都属于“未定义”。
1.3 模块内的 __all__ 变量
通常使用import *
语句将导入模块内的所有名称,如果想只导入部分指定的名称,可以在模块内定义了一个__all__
变量保存需要导入的名称,其类型为list
类型。
一个模块内如果定义了__all__
变量,则使用import *
语句导入模块的所有名称时,将只导入__all__
变量中保存的名称。
示例:
脚本文件demo.py
:
# 使用 import * 导入模块名称时, 将只导入 fun1 和 aa
__all__ = ["fun1", "aa"]
def fun1():
print("demo fun1")
def fun2():
print("demo fun2")
aa = 100
bb = "Hello"
访问 demo 模块:
>>> from demo import * # 导入 demo 模块内的名称
>>> fun1() # 正常访问
demo fun1
>>> aa # 正常访问
100
>>> fun2() # fun2 未定义
NameError: name 'fun2' is not defined
>>> bb # bb 未定义
NameError: name 'bb' is not defined
1.4 模块搜索路径
搜索模块官网介绍: The-module-search-path
当一个名为demo
的模块被import
时,解释器首先在 内置模块 中查找该模块。如果找不到,则解释器从sys.path
变量给出的目录列表中逐一查找出名为demo.py
的文件。如果都找不到,则抛出ModuleNotFoundError
异常。
1.4.1 sys.path 的初始化值依次如下:
被执行的脚本文件所在目录(没有指定脚本文件时为当前目录)
- PYTHONPATH 环境变量指定的目录(添加多个路径使用
os.pathsep
路径分隔符分隔) - 安装 Python 时决定的默认设置(即默认安装的 Python 库所在的相关目录列表)
- PYTHONPATH 环境变量指定的目录(添加多个路径使用
在初始化后,Python 程序中可以更改sys.path
(增加或移除目录)。更改后import
查找模块时将从最新的sys.path
目录列表中依次查找指定模块。
1.4.2 sys.path 的值示例:
$ export PYTHONPATH="/aa:/bb/cc" # 设置 PYTHONPATH 环境变量(Linux)
$ python3 # 运行 Python 解释器, 没有指定脚本文件
>>> import sys
>>> sys.path
[
'', # 1. 没有指定脚本文件, 则第一个目录为空字符串, 即表示当前目录
'/aa', # 2. 从 PYTHONPATH 环境变量中获取的路径
'/bb/cc', # 2. 从 PYTHONPATH 环境变量中获取的路径
'.../lib/python37.zip', # 3. 以下的为其他默认路径(省略前缀)
'.../lib/python3.7',
'.../lib/python3.7/lib-dynload',
'.../lib/python3.7/site-packages'
]
1.4.3 运行脚本文件时 sys.path 的值示例:
脚本文件:/aa/bb/demo.py
import sys
print(sys.path)
运行脚本文件:
$ python3 /aa/bb/demo.py # 运行指定的脚本文件
[
'/aa/bb', # 有指定脚本文件, 则第一个目录为脚本文件所在目录
'.../lib/python37.zip',
'.../lib/python3.7',
'.../lib/python3.7/lib-dynload',
'.../lib/python3.7/site-packages'
]
1.5 模块内的 __name__ 属性
模块内有一个 __name__
属性,表示模块的名称。模块可以被其他模块导入执行,也可以自身执行。
当模块被其他模块导入执行时,__name__
属性的值为模块的名称;当模块自身被执行时,__name__
属性的值为 "__main__"
。
脚本文件 demo.py
:
if __name__ == "__main__":
print("模块自身执行")
else:
print("被其他模块导入执行")
访问 demo 模块:
$ python3 demo.py
模块自身执行
$ python3
>>> import demo
被其他模块导入执行
通过__name__
属性可以判断当前模块是否为自身被执行,因此可以在 Python 程序的启动脚本文件内定义一个main
函数作为程序的主函数入口,并通过判断是否为自身被执行来运行主函数,如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
def main():
print("主函数被执行")
if __name__ == "__main__":
main()
1.6 标准模块(库)
Python 安装时附带了一个标准模块库: https://docs.python.org/zh-cn/3/library/index.html
一些模块内置于解释器中,它们不属于语言核心内容,只是为了提高的效率或提供系统调用等操作系统原生的访问。例如winreg
模块只在 Windows 操作系统上才提供。一个需要特别注意的模块sys
,它被内嵌到每一个 Python 解释器中,其中变量sys.ps1
和sys.ps2
定义了交互模式下的主要和辅助提示字符串:
>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = "$ "
$ print("Hello")
Hello
$ sys.ps2 = "*** "
$ 1 + 2 \
*** + 3
6
$
sys.ps1
和sys.ps2
这两个变量只在 交互模式 下运行解释器时才被定义,脚本文件中访问这两个变量将抛出 AttributeError 异常。
1.7 第三方模块(库)
Python 第三方库获取: https://pypi.org
除了内置的一些标准模块库,还有许多第三方发布的各类模块库,可以下载下来安装到本地,或通过pip
命令在线安装(见后面的 pip 命令介绍)。
1.8 dir() 函数
内置函数dir(p_object=None)
可用于查找一个模块内定义的有效名称(变量、函数、类、模块等)列表,返回一个字符串列表:
>>> import sys
>>> dir(sys) # 列出 sys 模块内的名称(结果太多, 省略部分)
[
'__doc__', '__name__', '__package__',
'__stderr__', '__stdin__', '__stdout__',
...
'api_version', 'argv',
'stderr', 'stdin', 'stdout',
'thread_info', 'version', 'version_info'
]
>>> sys.version
'3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 16:52:21) \n[Clang 6.0 (clang-600.0.57)]'
# PS: dir() 函数不会列出内置函数和变量的名称。
实际上 dir 函数的 p_object 参数接收的是一个对象, 可以是任意对象,在 Python 中一切皆是对象,因此 dir 函数可以查找任意对象所拥有的有效名称(变量、函数、类、模块等)列表,示例:
>>> s = "hello" # 定义一个字符串
>>> dir(s) # 列出字符串对象 s 所拥有的名称(结果太多, 省略部分)
[
'__add__', '__dir__', '__doc__', '__len__',
'find', 'index', 'lower', 'lstrip', 'replace',
...
'rfind', 'rindex', 'strip', 'upper'
]
>>> s.upper()
'HELLO'
>>> dir() # 不传参数(即默认传 None), 输出的是当前作用域中的名称列表
['__builtins__', '__doc__', '__name__', '__package__', 's']
>> dir(dir) # dir 函数本身也是一个对象, 也可以查找 dir 所拥有的名称列表
...
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__
变量。
有了包结构对模块的管理,一个复杂的模块库就可以把其中不同功能的模块细分到不同的子包中,使得更容易对代码功能的细致管理和使用,而且也不需要担心模块名称的重复问题。下面是官网给出的假设处理声音文件和数据的模块库的可能的包结构:
sound/ # 顶层包(文件夹)
__init__.py # 顶层包的初始化脚本文件
formats/ # 用于文件格式转换的子包(文件夹)
__init__.py # 子包的初始脚本文件
wavread.py # 包内的具体模块的脚本文件
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
effects/ # 处理声音效果的子包
__init__.py
echo.py
surround.py
reverse.py
...
filters/ # 过滤器子包
__init__.py
equalizer.py
vocoder.py
karaoke.py
...
当import
一个包中的模块sound.formats.wavread
时,Python 解释器将从sys.path
列表的目录下逐一搜索出路径为sound/formats/wavread.py
的文件。因此顶层包必须在sys.path
目录列表中的其中一个目录下,否则将抛出ModuleNotFoundError
的异常。
TODO: 包模块中的变量 __name__
, __path__
, __package__
2.2 包中模块的导入
通过全名导入具体模块:
import sound.formats.wavread # 直接通过全名导入模块
sound.formats.wavread.fun(...) # 上面的导入方法, 引用时必须使用全名
# 假设 fun 是模块 wavread 中的一个函数
通过全名导入具体模块,并为模块起一个新的别名:
import sound.formats.wavread as wr # 直接通过全名导入模块
wr.fun(...) # 通过别名引用
从具体模块中导入一个函数:
from sound.formats.wavread import fun # 导入具体模块中的一个函数
fun(...) # 直接使用导入的函数名
从包中导入模块:
from sound.formats import wavread # 从包 sound.formats 中导入模块 wavread
wavread.fun(...) # 上面的导入方法, 引用模块时只需要使用 wavread
从包中导入所有模块:
from sound.formats import * # 从包 sound.formats 中导入模块所有模块
wavread.fun1(...) # 导入后, 包中的所有模块在当前都可直接引用
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
__all__ = ["wavread", "wavwrite"]
在代码中导入模块:
# 只会导入 wavread.py 和 wavwritep.py 模块
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
的模块目录结构:
. # MyModule 目录
|--- steup.py # 模块的配置文件
|--- toppkg # 顶层包
|--- suba # 子包
| |--- aa.py # 脚本文件
| |--- bb.py # 脚本文件
| |--- __init__.py
|--- subb # 子包
| |--- cc.py # 脚本文件
| |--- dd.py # 脚本文件
| |--- __init__.py
|--- __init__.py
(2) 编辑 steup.py
配置文件:
from distutils.core import setup
setup(name="MyModule", # 模块名称
version="1.0", # 模块版本
description="my custom module", # 模块描述
author="Me", # 模块作者
author_email="xxxx@qq.com", # 作者邮箱
py_modules=["toppkg.suba.aa", # 此模块包所包含的所有模块(py脚本文件)
"toppkg.suba.bb",
"toppkg.subb.cc",
"toppkg.subb.dd"])
(3) 构建模块
运行 setup.py 脚本,构建模块: python3 setup.py build
构建成功后生成一个 build 目录:
. # MyModule 目录
|--- build # 构建生产的 build 目录
| |--- lib
| |--- toppkg
| |--- suba
| | |--- aa.py
| | |--- bb.py
| | |--- __init__.py
| |--- subb
| |--- cc.py
| |--- dd.py
| |--- __init__.py
|--- steup.py
|--- toppkg
|--- suba
| |--- aa.py
| |--- bb.py
| |--- __init__.py
|--- subb
| |--- cc.py
| |--- dd.py
| |--- __init__.py
|--- __init__.py
(4) 打包模块
运行 setup.py 脚本,打包模块: python3 setup.py sdist
打包成功后,生成一个 MyModule-1.0.tar.gz 压缩包:
. # MyModule 目录
|--- build
| |--- lib
| |--- toppkg
| |--- suba
| | |--- aa.py
| | |--- bb.py
| | |--- __init__.py
| |--- subb
| |--- cc.py
| |--- dd.py
| |--- __init__.py
|--- dist
| |--- MyModule-1.0.tar.gz # 打包生成的压缩包
|--- steup.py
|--- toppkg
|--- suba
| |--- aa.py
| |--- bb.py
| |--- __init__.py
|--- subb
| |--- cc.py
| |--- dd.py
| |--- __init__.py
|--- __init__.py
MyModule-1.0.tar.gz
压缩包即为 最终可发布 的模块包,其内部目录结构为:
MyModule-1.0.tar.gz
|--- MyModule-1.0 # 压缩包内顶层文件夹
|--- setup.py # 配置文件
|--- PKG-INFO # 包的信息文件
|--- toppkg # 源码包
|--- suba
| |--- aa.py
| |--- bb.py
| |--- __init__.py
|--- subb
| |--- cc.py
| |--- dd.py
| |--- __init__.py
|--- __init__.py
3.2 模块安装
(1) 获取到模块安装包MyModule-1.0.tar.gz
,解压得到文件夹MyModule-1.0
:
MyModule-1.0
|--- setup.py
|--- PKG-INFO
|--- toppkg
|--- suba
| |--- aa.py
| |--- bb.py
| |--- __init__.py
|--- subb
| |--- cc.py
| |--- dd.py
| |--- __init__.py
|--- __init__.py
(2) 安装模块包
# 先进入解压后的模块文件夹
cd MyModule-1.0
# 执行 setup.py 脚本安装
python3 setup.py install
# 默认把模块安装到 Python 安装目录下的 site-packages 文件夹下
指定安装目录:
python3 setup.py install --prefix=安装目录
# 执行完后, 模块将安装到: {安装目录}/lib/site-packages
(3) 引用模块
安装完后,确保安装路径在sys.path
目录列表中,在 Python 代码中即可直接导入使用:
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
文件安装:
$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
$ python3 get-pip.py
升级 pip
的版本:
# 升级 pip 版本, 需要使用 python 的命令来升级
python3 -m pip install --upgrade pip
4.2 pip 命令
pip 安装软件包命令相关官网链接:
- Installing Packages
- Installing from PyPI
- Upgrading packages
4.2.1 安装软件包
pip3 install PackageName # 普通安装(在线安装)
pip3 install whl_package_file.whl # 离线安装, 先下载好 whl 安装文件再安装
pip3 install --upgrade PackageName # 升级软件包
pip3 install "PackageName==1.0.4" # 指定特定版本
pip3 install "PackageName>=1.0.4" # 指定最小版本
pip3 search PackageNameKeyword # 从 PyPI.ORG 在线搜索软件包
pip3 download PackageName # 下载软件包(默认下载到当前目录)
pip3 check PackageName # 校验已安装的软件包是否已具有兼容的依赖
4.2.2 卸载软件包
pip3 uninstall PackageName
4.2.3 查看软件包
pip3 list # 列出已安装的所有软件包
pip3 freeze # 以必需的格式列出已安装的软件包
pip3 show [--files] PackageName # 查看某个软件包的详细信息
4.2.4 pip 命令帮助
$ pip3 --help
Usage:
pip3 <command> [options]
or
python3 -m pip <command> [options]
Commands:
install Install packages.
download Download packages.
uninstall Uninstall packages.
freeze Output installed packages in requirements format.
list List installed packages.
show Show information about installed packages.
check Verify installed packages have compatible dependencies.
config Manage local and global configuration.
search Search PyPI for packages.
wheel Build wheels from your requirements.
hash Compute hashes of package archives.
completion A helper command used for command completion.
help Show help for commands.
General Options:
-h, --help Show help.
--isolated Run pip in an isolated mode, ignoring
environment variables and user configuration.
-v, --verbose Give more output. Option is additive, and can be
used up to 3 times.
-V, --version Show version and exit.
-q, --quiet Give less output. Option is additive, and can be
used up to 3 times (corresponding to WARNING,
ERROR, and CRITICAL logging levels).
--log <path> Path to a verbose appending log.
--proxy <proxy> Specify a proxy in the form
[user:passwd@]proxy.server:port.
--retries <retries> Maximum number of retries each connection should
attempt (default 5 times).
--timeout <sec> Set the socket timeout (default 15 seconds).
--exists-action <action> Default action when a path already exists:
(s)witch, (i)gnore, (w)ipe, (b)ackup, (a)bort).
--trusted-host <hostname> Mark this host as trusted, even though it does
not have valid or any HTTPS.
--cert <path> Path to alternate CA bundle.
--client-cert <path> Path to SSL client certificate, a single file
containing the private key and the certificate
in PEM format.
--cache-dir <dir> Store the cache data in <dir>.
--no-cache-dir Disable the cache.
--disable-pip-version-check
Don't periodically check PyPI to determine
whether a new version of pip is available for
download. Implied with --no-index.
--no-color Suppress colored output
还没有评论,来说两句吧...