Python|虚拟环境及包管理工具pipenv[荐]


前面我们提过Python多版本管理工具pyenv,虚拟环境管理工具pyenv-virtualenv和virtualenv.今天要请出的这位可以说是神器了:通过自动把项目和环境关联实现包管理和环境管理.


优势:

  • 自动创建/进入虚拟环境
  • 自动加载.env里的环境变量
  • 安装包管理,替代requirements.txt,而且方便查看依懒

安装

$ pip install pipenv

查看

$ pipenv --venv
No virtualenv has been created for this project yet!
Aborted!

创建

$ pipenv install --python ~/.pyenv/versions/3.8.2/bin/python3.8
Creating a virtualenv for this project...
Pipfile: /Users/rainbird/testpro/Pipfile
Using /Users/rainbird/.pyenv/versions/3.8.2/bin/python3.8 (3.8.2) to create virtualenv...
⠴ Creating virtual environment...Already using interpreter /Users/rainbird/.pyenv/versions/3.8.2/bin/python3.8
Using base prefix '/Users/rainbird/.pyenv/versions/3.8.2'
New python executable in /Users/rainbird/.local/share/virtualenvs/testpro-_sTYLKQx/bin/python3.8
Also creating executable in /Users/rainbird/.local/share/virtualenvs/testpro-_sTYLKQx/bin/python
Installing setuptools, pip, wheel...
done.
Running virtualenv with interpreter /Users/rainbird/.pyenv/versions/3.8.2/bin/python3.8

✔ Successfully created virtual environment!
Virtualenv location: /Users/rainbird/.local/share/virtualenvs/testpro-_sTYLKQx
Creating a Pipfile for this project...
Pipfile.lock not found, creating...
Locking [dev-packages] dependencies...
Locking [packages] dependencies...
Updated Pipfile.lock (db4242)!
Installing dependencies from Pipfile.lock (db4242)...
  🐍   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 0/0 — 00:00:00
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.

Profile内容解析

$ cat Pipfile
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]

[requires]
python_version = "3.8"

source用来设置仓库地址,即从哪下载虚拟环境所需要的包
packages用来指定项目依赖的包,即你安装了的包
dev-packages用来指定开发环境需要的包,这类包只用于开发过程,不用与生产环境,比如单元测试相关的包,只在开发阶段有用,这样分开便于管理。
requires 中指定目标Python版本

Pipfile.lock

cat Pipfile.lock
{
    "_meta": {
        "hash": {
            "sha256": "7f7606f08e0544d8d012ef4d097dabdd6df6843a28793eb6551245d4b2db4242"
        },
        "pipfile-spec": 6,
        "requires": {
            "python_version": "3.8"
        },
        "sources": [
            {
                "name": "pypi",
                "url": "https://pypi.org/simple",
                "verify_ssl": true
            }
        ]
    },
    "default": {},
    "develop": {}
}

Pipfile.lock中记录了当前虚拟环境中安装的依赖的版本号以及哈希,以保证每次根据这些值装出来的依赖都是一致的,该文件用来保证包的完整性。记住,任何情况下不要手动修改该文件!
项目提交时,可将Pipfile 文件和Pipfile.lock文件一并提交,给其他开发人员克隆下载,他们可以根据此Pipfile文件运行命令pipenv install生成自己的虚拟环境

查看虚拟环境

$ pipenv --venv
/Users/rainbird/.local/share/virtualenvs/testpro-_sTYLKQx

安装Python包
使用pipenv可以轻松优雅地管理项目所依赖的包,下面通过实际使用案例来学习其用法

安装命令

pipenv install requests   #在项目所在虚拟环境中安装requests
pipenv install requests==1.3.1    #安装requests并指定其版本
pipenv install --dev requests      #安装requests包并将其关联为只在开发环境中需要的包

卸载命令

pipenv uninstall requests #在项目所在虚拟环境中卸载requests
pipenv uninstall --all          #从虚拟环境中移除所有已安装的包,但Pipfile.lock文件不受影响
pipenv uninstall --all--dev     #从虚拟环境中卸载所有开发包,并从Pipfile文件中移除这些包

更新命令

pipenv update requests          #在项目中更新requests包
pipenv update                   #更新项目中所有的包
pipenv update --outdated        #查看现有包哪些已经过期

查看命令

pipenv grash                    #显示现有的依赖包
pipenv lock                     #更新Pipfile.lock文件锁定当前环境的依赖版本
上面代码中值得一提的是--dev标志,加了此标志的包只用于开发环境,安装包记录在Pipfile中的dev-package中,如果别人克隆你的Profile文件后使用命令pipenv install创建虚拟环境,默认不会安装dev-package下的安装包,除非使用命令pipenv install --dev
Pipefile 和 Pipefile.lock 都会按照你的操作进行自动的更新,如果需要手动修改包的依赖条件,手工编辑 Pipefile 并进行安装即可。

兼容virtualenv
pipenv可以像virtualenv一样使用命令生成requirements.txt文件。

pipenv lock -r --dev > requirements.txt

同样的,也可以像virtualenv一样通过requirements.txt文件安装包

pipenv install -r requirements.txt

这个命令让我们可以重用以前requirements.txt文件来构建我们新的开发环境,把我们的项目顺利的迁到pipenv。

进入虚拟环境
跟virtualenv一样,要在虚拟环境中运行代码,“激活”虚拟环境。假设可以使用命令pipenv shell进入我们创建的虚拟环境。如下

pipenv shell             # 激活当前虚拟环境,当项目根目录下有 .env 文件时,自动解析添加环境变量
pipenv --where           # 查看当前工作目录
pipenv --venv            # 查看当前虚拟环境路径
pipenv --py              # 查看当前python解释器路径
pipenv --envs            # 查看可用环境变量

执行完命令,命令提示符前出现了如(TestPipenv-tmf99lpc)的前缀,那是我们虚拟环境的名字,这代表我们已经进入了虚拟环境,在其中使用的命令是虚拟环境版本的命令,不是系统的命令。举个例子,如下图

这里进入的是虚拟环境里的Python版本,而不是我们系统环境的Python版本。同样的, 虚拟环境中使用的pip是虚拟环境下的pip,用其安装的库会装在虚拟环境中,不会与系统或其他项目的库冲突。

进入虚拟环境后,我们可以在虚拟环境中运行我们的项目代码,如下

如果想退出虚拟环境,输入exit即可。
如果想在不进入虚拟环境的情况下使用虚拟环境运行代码,可以使用pipenv run命令,如下

pipenv run index.py

删除虚拟环境
如果想删除虚拟环境,可以使用命令pipenv --rm, 如下:

pipenv --rm

值得注意的是,删除了虚拟环境,如果再次使用pipenv shell,会在该目录下创建一个新的虚拟环境,然后再进入虚拟环境。

遇到的问题

  • AttributeError: 'NoneType' object has no attribute 'find_all_python_versions'
pipenv install --python 3.8.2
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/2.7/bin/pipenv", line 11, in <module>
    sys.exit(cli())
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/vendor/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/vendor/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/vendor/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/vendor/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/vendor/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/vendor/click/decorators.py", line 64, in new_func
    return ctx.invoke(f, obj, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/vendor/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/vendor/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/cli/command.py", line 254, in install
    editable_packages=state.installstate.editables,
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/core.py", line 1741, in do_install
    pypi_mirror=pypi_mirror,
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/core.py", line 574, in ensure_project
    pypi_mirror=pypi_mirror,
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/core.py", line 494, in ensure_virtualenv
    python = ensure_python(three=three, python=python)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/core.py", line 397, in ensure_python
    path_to_python = find_a_system_python(python)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/core.py", line 360, in find_a_system_python
    python_entry = finder.find_python_version(line)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/vendor/backports/functools_lru_cache.py", line 137, in wrapper
    result = user_function(*args, **kwds)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/vendor/pythonfinder/pythonfinder.py", line 113, in find_python_version
    return self.system_path.find_python_version(
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/vendor/pythonfinder/pythonfinder.py", line 54, in system_path
    ignore_unsupported=self.ignore_unsupported,
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/vendor/pythonfinder/models/path.py", line 451, in create
    ignore_unsupported=ignore_unsupported,
  File "<attrs generated init 0c5e0ca48e6d72e07a67727a626d079225b052cd>", line 38, in __init__
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/vendor/pythonfinder/models/path.py", line 116, in __attrs_post_init__
    self._setup_pyenv()
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/vendor/pythonfinder/models/path.py", line 196, in _setup_pyenv
    version_glob_path="versions/*", ignore_unsupported=self.ignore_unsupported
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/vendor/pythonfinder/models/python.py", line 156, in create
    sort_function=sort_function, version_glob_path=version_glob_path)
  File "<attrs generated init 0d637cc9107620abb7d1640cbc38b38ba03a1912>", line 17, in __init__
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pipenv/vendor/pythonfinder/models/python.py", line 114, in get_versions
    entry = next(iter(version_path.find_all_python_versions()), None)
AttributeError: 'NoneType' object has no attribute 'find_all_python_versions'

解决

rm ~/.pyenv/versions/.DS_Store

相关博文

About rainbird

IOS攻城狮
This entry was posted in linux, Mac, Python and tagged , , , , , , , . Bookmark the permalink.

发表评论