使用 pipenv + direnv 来管理 python 的项目依赖环境

以前我一直在用 virtualenv + virtualenvwrapper 插件,其实用的也好好的,就是依赖不能像 node 的 yarn 一样区分开发和生产,而且没有 lock 文件,锁定版本都靠 requirements.txt 文件,略有不便。今天无聊搜了一下 python 的包管理软件,发现了 pipenv。初步看了下介绍 ,这不就是我想要的嘛。遂尝试将以前的一个爬虫项目转为使用 pipenv 管理。

安装 pipenv

安装 pipenv 非常容易,只要用 pip install pipenv 命令安装就好。

基本使用方法

先进入项目目录

cd ~/dev/mh

安装相关依赖

pipenv install Scrapy

这时候注意了,当项目还没有建立 env 的时候,pipenv 会自动的建立一个对应当前项目的 env 环境,并把依赖包安装进去。在我的机器上是在 ~/.virtualenvs 文件夹里面。然后会生成 Pipfile 文件,里面有依赖包的信息,格式是 toml。我注意到里面还有指定 url 可以使用国内的镜像来加速安装。

pipenv install ipython --dev

当加入 --dev 参数时,安装的依赖就会放到 [dev-packages] 下面,在生产环境可以不安装这个里面的包,减小体积。

锁定版本

当安装包所有的依赖包后,执行 pipenv lock 会在 Pipfile.lock 里面记录当前所有依赖的版本,当部署到新机器上的时候执行 pipenv sync 就可以安装对应的依赖了,非常方便。

在新机器上同步环境

# 安装环境,生产环境用这条
pipenv sync 

# 同时安装开发依赖
pipenv sync -d

查看依赖关系

$ pipenv graph
autopep8==1.3.5
  - pycodestyle [required: >=2.3, installed: 2.3.1]
flake8==3.5.0
  - mccabe [required: >=0.6.0,<0.7.0, installed: 0.6.1]
  - pycodestyle [required: >=2.0.0,<2.4.0, installed: 2.3.1]
  - pyflakes [required: >=1.5.0,<1.7.0, installed: 1.6.0]
ipython==6.4.0
  - appnope [required: Any, installed: 0.1.0]
  - backcall [required: Any, installed: 0.1.0]
  - decorator [required: Any, installed: 4.3.0]
  - jedi [required: >=0.10, installed: 0.12.1]
    - parso [required: >=0.3.0, installed: 0.3.0]
  - pexpect [required: Any, installed: 4.6.0]
    - ptyprocess [required: >=0.5, installed: 0.6.0]
  - pickleshare [required: Any, installed: 0.7.4]
  - prompt-toolkit [required: >=1.0.15,<2.0.0, installed: 1.0.15]
    - six [required: >=1.9.0, installed: 1.11.0]
    - wcwidth [required: Any, installed: 0.1.7]
  - pygments [required: Any, installed: 2.2.0]
  - setuptools [required: >=18.5, installed: 39.2.0]
  - simplegeneric [required: >0.8, installed: 0.8.1]
  - traitlets [required: >=4.2, installed: 4.3.2]
    - decorator [required: Any, installed: 4.3.0]
    - ipython-genutils [required: Any, installed: 0.2.0]
    - six [required: Any, installed: 1.11.0]
Pillow==5.2.0
Scrapy==1.5.0
  - cssselect [required: >=0.9, installed: 1.0.3]
  - lxml [required: Any, installed: 4.2.3]
  - parsel [required: >=1.1, installed: 1.4.0]
    - cssselect [required: >=0.9, installed: 1.0.3]
    - lxml [required: >=2.3, installed: 4.2.3]
    - six [required: >=1.5.2, installed: 1.11.0]
    - w3lib [required: >=1.8.0, installed: 1.19.0]
      - six [required: >=1.4.1, installed: 1.11.0]
  - PyDispatcher [required: >=2.0.5, installed: 2.0.5]
  - pyOpenSSL [required: Any, installed: 18.0.0]
    - cryptography [required: >=2.2.1, installed: 2.2.2]
      - asn1crypto [required: >=0.21.0, installed: 0.24.0]
      - cffi [required: >=1.7, installed: 1.11.5]
        - pycparser [required: Any, installed: 2.18]
      - idna [required: >=2.1, installed: 2.7]
      - six [required: >=1.4.1, installed: 1.11.0]
    - six [required: >=1.5.2, installed: 1.11.0]
  - queuelib [required: Any, installed: 1.5.0]
  - service-identity [required: Any, installed: 17.0.0]
    - attrs [required: Any, installed: 18.1.0]
    - pyasn1 [required: Any, installed: 0.4.3]
    - pyasn1-modules [required: Any, installed: 0.2.2]
      - pyasn1 [required: >=0.4.1,<0.5.0, installed: 0.4.3]
    - pyopenssl [required: >=0.12, installed: 18.0.0]
      - cryptography [required: >=2.2.1, installed: 2.2.2]
        - asn1crypto [required: >=0.21.0, installed: 0.24.0]
        - cffi [required: >=1.7, installed: 1.11.5]
          - pycparser [required: Any, installed: 2.18]
        - idna [required: >=2.1, installed: 2.7]
        - six [required: >=1.4.1, installed: 1.11.0]
      - six [required: >=1.5.2, installed: 1.11.0]
  - six [required: >=1.5.2, installed: 1.11.0]
  - Twisted [required: >=13.1.0, installed: 18.4.0]
    - Automat [required: >=0.3.0, installed: 0.7.0]
      - attrs [required: >=16.1.0, installed: 18.1.0]
      - six [required: Any, installed: 1.11.0]
    - constantly [required: >=15.1, installed: 15.1.0]
    - hyperlink [required: >=17.1.1, installed: 18.0.0]
      - idna [required: >=2.5, installed: 2.7]
    - incremental [required: >=16.10.1, installed: 17.5.0]
    - zope.interface [required: >=4.4.2, installed: 4.5.0]
      - setuptools [required: Any, installed: 39.2.0]
  - w3lib [required: >=1.17.0, installed: 1.19.0]
    - six [required: >=1.4.1, installed: 1.11.0]

执行 pipenv graph 命令会像上面那样显示出各个包的依赖关系。

配合 direnv 使用

direnv 工具可以在进入目录时自动切换当前的环境,不需要手动执行 pipenv shell。我用的是mac,使用 brew install direnv 命令安装,其它的系统参考 https://github.com/direnv/direnv

在 shell 启动时载入 direnv

我用的是 fish ,按照官方的说明 https://github.com/direnv/direnv#fish ,只要在 fish 的启动配置 (一般是在 ~/.config/fish/config.fish,我用了 oh-my-fish ,所以在 ~/.config/omf/init.fish) 里面加入 eval (direnv hook fish) 这条命令就可以了。

在项目目录里面启用

现在已经安装好 direnv 了,到项目的目录里面添加一个 .envrc 文件,内容是 layout_pipenv,保存后再执行 direnv allow。这样就启动了当前目录的自动切换环境功能,只要进入项目目录就会自动执行 pipenv shell

PS: 我发现在 vscode 里面,安装了 python 插件后也能自动识别 .envrc 文件,打开项目后自动加载对应的环境。

vscode
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容

  • Ubuntu的发音 Ubuntu,源于非洲祖鲁人和科萨人的语言,发作 oo-boon-too 的音。了解发音是有意...
    萤火虫de梦阅读 99,216评论 9 467
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,856评论 25 707
  • linux资料总章2.1 1.0写的不好抱歉 但是2.0已经改了很多 但是错误还是无法避免 以后资料会慢慢更新 大...
    数据革命阅读 12,149评论 2 34
  • 我记得我第一眼看见你就很喜欢你。你很漂亮。这叫一见钟情。当时的自己是一个不好看的人 有着很短的头发。以致后来的自己...
    小小的期许阅读 358评论 0 0
  • 黑夜是很神奇的颜色,习惯一个人待着黑暗的房间里,不开灯,睁着眼睛,想着一些乱七八糟的事情,或哭,或笑。 最多的时候...
    向左向右1871阅读 129评论 0 2