神刀安全网

如何解决Python包依赖问题

以简洁高效(指编程较为高效, 而不是运行速度)出名的Python, 在包依赖问题上有时候让人挠头.

一些新手复制了Github上的项目准备运行, 很多时候会在包依赖这一步上卡个半天.(这里推荐新手最好在基于Linux的系统或者Mac上, 一些包[比如Scrapy的Win32相关依赖]可能无法直接通过包管理工具安装, 会让新手从入门到放弃). 其他涉及到项目需要到其他机器部署时, 也会遇到包依赖问题.

# 这可能是部署过程中最常见的错误 ModuleNotFoundError: No Module named 'XXX' 

通过pip输出依赖

pip freeze > requirements.txt 

这个命令可能是很多同学用来输出依赖的命令, 但它输出的是当前环境下(
笔者默认你使用的是Python的虚拟环境)的所有包, 也就是输出当前你安装的全部非Python标准库包)
笔者在自己终端上试了一下, 输出的文件如下: (这里暴露了我没有按项目建虚拟环境的烂习惯(逃)

# 省略N个库 .... Django==1.11.8 django-mongonaut==0.2.21 docopt==0.6.2 Flask==0.10.1 Flask-Bootstrap==3.0.3.1 Flask-Login==0.3.1 Flask-Mail==0.9.0 Flask-Migrate==1.1.0 Flask-Moment==0.2.1 Flask-PageDown==0.1.4 Flask-Script==0.6.6 Flask-SQLAlchemy==1.0 Flask-WTF==0.9.4 ForgeryPy==0.1 html5lib==1.0b3 hyperlink==17.3.1 idna==2.6 incremental==17.5.0 itsdangerous==0.23 Jinja2==2.7.1 lxml==4.1.1 Mako==0.9.1 Markdown==2.3.1 MarkupSafe==0.18 mongoengine==0.9.0 numpy==1.14.0 pandas==0.22.0 parsel==1.3.1 pdfkit==0.6.1 pipreqs==0.4.9 pyasn1==0.4.2 pyasn1-modules==0.2.1 pycparser==2.18 PyDispatcher==2.0.5 pymongo==2.8 PyMySQL==0.7.9 pyOpenSSL==17.5.0 python-dateutil==2.6.1 pytz==2017.3 queuelib==1.4.2 requests==2.18.4 requests-file==1.4.3 scrape==0.9.12 Scrapy==1.5.0 ... # 省略N+1个库 

对于按项目建环境的同学, 这种输出方式是没有多大问题的
只要部署的时候在终端键入pip install -r requirements.txt就可以安装好依赖了, 但是对于没有严格区分项目环境的同学, 一次性安装了其他的包, 并不是一个好的解决方案.

通过pipreqs库输出依赖

如这个库的名称所示, 就是为了方便管理依赖而生.
与pip直接导出全部不同, pipreqs只导出指定项目下Python文件import的库
用法如下

# 安装 pip install pipreqs # 切换到项目目录 # 输出requirements.txt到项目根目录下 pipreqs --use-local ./ 

这里我切换到一个Django项目目录下, 打开requirements.txt, 内容是:

pandas==0.22.0 django_debug_toolbar.egg==info mongoengine==0.9.0 Django==1.11.8 

瞬间清爽不少.

通过Pipenv管理依赖

Pipenv, 汇集了Pip,Pipfile和Virtualenv的功能,是一个强大的命令行工具。

这里展示最简单的用法

  1. pip install pipenv安装好库.
  2. 切换到项目根目录
  3. 终端键入Pipenv install

如果你尚未建立requirements.txt那么将会得到一个空白的Pipfile文本文件, 此时我们在命令行中使用pipenv install 包名, 会在Pipefile写入对应包信息, 之后用户要安装依赖时, 使用pipenv install即可.
如果你已经建立, 终端上会输出以下信息:

requirements.txt found, instead of Pipfile! Converting… Warning: Your Pipfile now contains pinned versions, if your requirements.txt did.  We recommend updating your Pipfile to specify the "*" version, instead. ... 

上面的输出意思是: 找到了requirements.txt, 但不是Pipfile, 正在转换…
Pipefile现在将包含固定版本信息, 如果你的requirements.txt中已包含.
我们推荐升级你的Pipefile到指定版本…

输出Pipenv文件, 得到以下内容:

[[source]] url = "https://pypi.org/simple" verify_ssl = true name = "pypi"  [packages] mongoengine = "==0.9.0" "django-debug-toolbar.egg" = "==info" django = "==1.11.8" pandas = "==0.22.0"  [dev-packages]  [requires] python_version = "3.6" 

可以清楚的看到整个文件结构, 第一个是[source]是安装库所在源, 第二个是依赖库的信息, 第三个是当你开发环境所需要的包, 最后一个是Python版本.
当你需要区分开发环境和正式版本发布环境时, 可以使用以下命令:

pipenv install --dev 包名 

如果正式版本发布时, 键入Pipenv install, 将不会安装dev标记的包
除非其他开发人员键入Pipenv install -dev, 才会安装所有包.

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » 如何解决Python包依赖问题

分享到:更多 ()