python依赖管理基础教程

此去经年,夏梦未央。我以为你会是我最温暖的夏阳。只是我忘了,我们都无力阻止四季的轮转

Posted by yishuifengxiao on 2021-05-27

一 基本使用

Python 也需要维护项目相关的依赖包。通常我们会在项目的根目录下放置一个 requirement.txt 文件,用于记录所有依赖包和它的确切版本号。

requirement.txt 的内容长这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
alembic==1.0.10
appnope==0.1.0
astroid==2.2.5
attrs==19.1.0
backcall==0.1.0
bcrypt==3.1.6
bleach==3.1.0
cffi==1.12.3
Click==7.0
decorator==4.4.0
defusedxml==0.6.0
entrypoints==0.3
...

requirements.txt的写法如下

1
2
3
4
5
-r base.txt # base.txt下面的所有包
pypinyin==0.12.0 # 指定版本(最日常的写法)
django-querycount>=0.5.0 # 大于某个版本
django-debug-toolbar>=1.3.1,<=1.3.3 # 版本范围
ipython # 默认(存在不替换,不存在安装最新版)

对于下面的语法

1
mock-django~=0.6.10

这是“兼容版本”version specifier

它相当于:mock-django >= 0.6.10, == 0.6.*,是一种整洁的匹配预期兼容版本的方法。用通俗的英语来说,这有点像是在说:“我需要一个mock django的版本,它至少和0.6.10一样新,但不是太新,以至于与它不兼容

这意味着它将选择包的最新版本,大于或等于0.6.10,但仍在0.6.*版本中,因此它不会下载0.7.0。如果包维护者尊重语义版本控制(语义版本控制声明中断更改只应在主要版本中发生),它可以确保您获得安全修复,但保持向后兼容性。

或者,如PEP 440所说:

For a given release identifier V.N , the compatible release clause is approximately equivalent to the pair of comparison clauses:

1
>= V.N, == V.*

requirements.txt可以通过pip命令自动生成和安装,这种情况更适用于此项目是单独的虚拟python环境
生成requirements.txt文件

1
2
pip freeze > requirements.txt
pip3 freeze > requirements.txt

安装requirements.txt依赖

1
2
pip install -r requirements.txt
pip3 install -r requirements.txt

3.下载requirements.txt中的依赖包到本地

1
pip download -d /tmp/packagesdir -r requirements.txt

4.安装下载到本地的依赖包

1
pip install --no-index --ignore-installed --find-links=/tmp/packagesdir -r requirements.txt

python依赖搜索地址

https://pypi.org/search/?q=&o=


二 环境混用

在导出依赖到 requirement.txt 文件时会有一种尴尬的情况。

你的本地环境不仅包含项目 A 所需要的依赖,也包含着项目 B 所需要的依赖。此时我们要如何做到只把项目 A 的依赖导出呢?

pipreqs 可以通过扫描项目目录,帮助我们仅生成当前项目的依赖清单。

通过以下命令安装:

1
pip install pipreqs

运行:

1
pipreqs ./

或者

1
pipreqs /home/project/location

如果执行此命令出现错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
λ pipreqs ./
Traceback (most recent call last):
File "c:\users\yishui\appdata\local\programs\python\python39\lib\runpy.py", line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File "c:\users\yishui\appdata\local\programs\python\python39\lib\runpy.py", line 87, in _run_code
exec(code, run_globals)
File "C:\Users\yishui\AppData\Local\Programs\Python\Python39\Scripts\pipreqs.exe\__main__.py", line 7, in <module>
File "c:\users\yishui\appdata\local\programs\python\python39\lib\site-packages\pipreqs\pipreqs.py", line 470, in main
init(args)
File "c:\users\yishui\appdata\local\programs\python\python39\lib\site-packages\pipreqs\pipreqs.py", line 406, in init
candidates = get_all_imports(input_path,
File "c:\users\yishui\appdata\local\programs\python\python39\lib\site-packages\pipreqs\pipreqs.py", line 122, in get_all_imports
contents = f.read()
UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 10: illegal multibyte sequence

可以使用

1
pipreqs --use-local --encoding=utf8 --force ./