从python开始的虚拟环境配置日志

文章概述

本来这篇文章写得是爬虫学习日志,但是后来发现前置工作也是虚拟环境的配置还是有待一提。日前在做cv的时候使用SIFT对图像的特征进行提取,当时没有手写SIFT函数,而是调用了opencv的一个函数,其中存在的一个问题是后来SIFT算法申请了专利,后续版本的opencv不再支持这个函数,于是当时搜索了很久找到支持该函数的旧版本,期间python版本还从3.7降到了3.68以支持这个函数的调用,而命令行输入python —version的时候仍然显示版本是3.7,这就显得库和包的版本控制比较混乱,然而当时我并没有意识到这个问题。后来电脑重装了一次,也是最近在学习爬虫的时候以及后来学习深度学习的时候我才开始重视python的包管理问题,目前看到的几种虚拟环境配置方式有:

  • virtualenv
  • conda env
  • docker

目前我已经尝试了virtualenv和conda env,docker还没有尝试过。感觉virtualenv和conda env两种使用上差不多,但是我选择了conda env,个人不使用virtualenv的原因在于:

  1. virtualenv似乎不支持jupyter notebook的集成
  2. conda env似乎比virtualenv多了一个生成配置文件并能根据配置文件创建相同环境的功能,这使得环境的在不同设备上的share更加地方便

但是最近在薅某IaaS提供商羊毛的时候,发现虽然有yml文件,但是将conda env从本地同步到远程仍然很麻烦,创建新的环境之后还要将该环境“注入”到jupyter notebook中,如果你没有某种快速部署的脚本的,这也是一个繁琐的步骤。

因此决定学习一下docker进一步对虚拟环境进行配置(还没学完)。

我学了一下docker,然后先用jupyter/tensorflow-notebook跑了一下,发现这种方式搭环境还是比较快的。然后我尝试了一下自己做一个docker jupyter notebook镜像用来做深度学习(因为我发现在自己的机器上写代码真的是心累,不禁拖慢的编码速度而且跑起来也很慢),我的思路是先pull一个ubuntu的镜像作为basic image,然后按照上面conda env的步骤创建虚拟环境,将kernel注入到jupyter notebook中,然后commit重新打包成新的镜像然后push到docker hub中。这样就可以在后续中pull下来试用啦。

emmmm,但是我感觉我实现的并不是很好,原因如下:

  1. 我理解这个images本质是一个ubuntu系统,run之后还需要进到里面启动jupyter notebook,过程感觉略有繁琐。
  2. 而对比jupyter/tensorflow-notebook其只需要run命令就可以,而不需要进到里面启动,但目前为止我没有搞懂这是怎么实现了。
  3. 做这个image的初衷是为了在远程服务器上使用自己习惯的环境,以及做开发环境的区分。但目前看来前者的目的貌似达到了,但是后者似乎可以通过run多个container来实现??比如我一个image包含ts+opencv和ts+panda(虽然没冲突但我举不出来例子),然后我可以通过run两个container(分别是ts+opencv的container和ts+panda的container)来实现开发环境区分的目的,这看来貌似我的做法有点多余?毕竟如果要配置新的环境又要进到容器进行配置,完了commit and push。

虚拟环境

virtualenv

安装

1
pip install virtualenvwrapper-win
1
pip install virtualenv

修改默认虚拟环境存放位置

2

查看虚拟环境

1
workon

创建虚拟环境

1
mkvirtualenv [env-name]

进入虚拟环境

1
workon [env-name]

退出虚拟环境

1
deactive

conda env

查看虚拟环境

1
2
conda env list
conda info -e

创建虚拟环境

1
conda create -n [env-name] python=[version]

进入虚拟环境

1
2
conda activate [env-name]
source activate [env-name]

退出虚拟环境

1
conda deactivate

复制虚拟环境

1
conda create -n [new-env-name] --clone [old-env-name]

删除虚拟环境

1
conda remove -n [env-name] --all

生成环境yml文件

1
conda env export > [env].yml

使用yml文件创建环境

1
conda env create -f [env].yml

yml文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
name: scrapy-env-clone
channels:
- defaults
dependencies:
- ca-certificates=2019.5.15=0
- certifi=2019.6.16=py37_0
- openssl=1.1.1c=he774522_1
- pip=19.1.1=py37_0
- python=3.7.3=h8c8aaf0_1
- setuptools=41.0.1=py37_0
- sqlite=3.28.0=he774522_0
- vc=14.1=h0510ff6_4
- vs2015_runtime=14.15.26706=h3a45250_4
- wheel=0.33.4=py37_0
- wincertstore=0.2=py37_0
prefix: D:\anaconda3\envs\scrapy-env

将conda env注入到jupyter notebook

package install

1
conda install ipykernel

激活虚拟环境

1
source activate [env]

安装ipykerneld

1
[env] pip install ipykernel

命令

1
python -m ipykernel install --user --name [env-name] --display-name "[jupyter-display-name]"

e.g

1
python -m ipykernel install --user --name deep_learning --display-name "Python [conda env:deep_learning]"

启动jupyter notebook

1
jupyter notebook

为jupyter notebook 安装 “conda” 选项卡

1
conda install nb_conda 

8

显示注入的环境

1
jupyter kernelspec list

删除注入的环境

1
jupyter kernelspec remove [env-name]

docker

前置工作

先安装docker,linux下安装docker见官网

docker基本操作见我的学习日志

快速搭建深度学习环境

如tensorflow,可以直接使用别人写好的镜像,如:

1
docker run -p 8888:8888 jupyter/tensorflow-notebook

或者

1
docker run -p 8888:8888 tensorflow/tensorflow

通过将docker容器的8888端口映射到外部机器的8888端口,都是集成Anaconda和jupyter进行快速开发。注意远程服务器需要打开安全组8888端口,输入http://ip:8888即可,首次登陆需要输入token凭证

4

该验证的位置在命令行中,但是这种方式非常的不稳定,如果网络从服务器中断开,那么容器的运行也会关闭,并且数据也会丢失。

所以更加安全稳定的方式是使用docker daemon守护进程来运行容器

1
docker run -d -p 8888:8888 --name notebook jupyter/tensorflow-notebook

6

输入这行命令之后命令行中仅仅输出了一个容器ID,那么要怎么才能够获取jupyter的token进行登录呢

1
docker logs --tail 3 notebook

7

防止下次登录服务器忘记了token,可以在jupyter notebook中reset你的密码。

上传你的代码可以从浏览器端上传,也可以使用jupyter notebook暴露出去的Terminal进行git clone

也可以使用下述命令进入到容器中

1
docker exec -it notebook /bin/bash

并使用exit以退出

定制化自己的python容器环境

以anaconda集成jupyter notebook开发为例

下载一个basic images

1
docker pull ubuntu:latest

运行并进入到容器中

1
2
docker run --name myEnv -it -d ubuntu /bin/bash
docker exec -it myEnv /bin/bash

更新库

1
sudo apt-get update

安装wget

1
sudo apt-get install wget

按照之前写的文章步骤安装anaconda及配置好jupyter,运行jupyter notebook,由于之前没有添加容器端口映射,所以容器内运行的jupyter notebook无法暴露出来,这时候可以先停止容器,并将其打包成镜像,然后在运行新的镜像时指定新的端口映射,命令如下:

1
2
3
4
5
6
#先停止容器
docker stop [CONTAINER ID]
#将容器commit成为一个镜像,时间略久
docker commit [CONTAINER ID] my-env
#运行容器
docker run -d -p 8888:8888 --name my-notebook my-env

进入容器,然后运行jupyter,此时发现jupyter: command not found,所以发现bash并没有更新进来,之前的操作并不是永久添加环境变量,只是临时,虽然容器并没有重启,但是重新exec也会丢失原本环境变量的配置,所以通过修改.bashrc文件来添加环境变量

1
2
3
4
5
vim ~/.bashrc

export PATH="$PATH:/root/anaconda3/bin"

source ~/.bashrc

然后本文按照上面写的conda env配置创建环境以及将环境注入到jupyter notebook中

完成之后exit退出

将该容器停止并重新打包生成一个新的镜像

登录docker账号

1
2
3
docker login
# docker ID
# docker password

上传到远程docker hub

1
docker push [IMAGE NAME]

我的docker image地址是https://cloud.docker.com/repository/docker/543877815/jupyter

使用方式

1
2
3
4
5
6
7
8
9
10
11
12
13
# 下载容器
docker run -p 8888:8888 -d -it 543877815/jupyter
[CONTAINER ID]

# 进入容器
docker exec -it [CONTAINER ID] /bin/bash
jupyter notebook --ip 0.0.0.0 --allow-root &

# 重写jupyter配置
jupyter notebook --generate-config

# 退出容器
exit