所谓:工欲善其事,必先利其器,我们的 Python 工程需要各种软件包的加持。与其事后手动管理依赖包和运行环境,不妨事先就将这些麻烦的问题交给更高效的工具处理,好让我们专注于工程开发。因此,在介绍 Python 之前,有必要先了解 conda 工具。
conda 自身是一个开源的软件包管理系统和环境管理系统。在这里,软件包既指代 Python 生态中流通的依赖包,也包含了那些由其它语言 ( 比如 C/C++) 开发的,可直接运行的二进制程序 ( 不需要用户再手动编译 ),如 mkl
,cuda
。这些二进制程序或许不会直接体现在用户的 Python 项目中,但是项目本身所依赖的包在底层可能会需要对这些二进制程序进行本地调用。
目前被开发者熟知的是 Anaconda,Ana- 是英文 "分析" 的前缀,它相当于 conda + Python + 180 个科学计算包的集成。见:Anaconda | The World's Most Popular Data Science Platform
Anaconda 的安装包约为 500 Mb。如果只想用 conda 的核心功能,则安装轻量版本的 Miniconda 即可。见:Miniconda — Conda documentation
安装过程中,建议不选择将 Anaconda 目录加入到 $PATH 环境变量中,以免与本机已经单独安装的 Python 路径产生冲突。这样做的结果是,直接使用终端和 conda 交互会出现找不到命令的提示。
不用对此过度担心。Anaconda 会单独提供 Anaconda Prompt 工具,它在启动时会设置必要的环境变量,从而允许用户和 conda 工具进行交互。
安装路径不要带空格,也最好不要带上中文。
在下文中,*title
样式的标题是重点部分,title*
样式的标题是可选部分。
conda 环境
该节内容来源于:Anaconda入门:安装及包与环境的管理 CSDN博客。
完整的 Anaconda 安装教程还可以参考:Anaconda介绍、安装及使用教程 - 知乎 (zhihu.com)
从思想上,conda 和 docker 这类容器管理工具很像。conda 创建各种环境的目的就在于隔离各个 Python 项目的运行环境,使得它们之间互不干扰。
在安装完毕之后,首先通过 conda --version
确认 conda 版本号信息。可以通过 update
对 conda 自身进行更新。
conda update conda
通过 env list
检查当前 conda 下的所有环境及其物理路径,conda 会将当前所在 ( 官方称之 "激活" ) 的环境标识为 *
号。在还没有激活任何环境的情况下,默认指向 base
环境。
conda env list
使用 list
可以打印出当前环境下的软件包清单。没有激活任何环境的情况下,默认打印 base
环境的软件包。
conda list
正是因为 conda 自带 Python 软件包的关系,我们无需再去 Python 官网单独安装。
通过 activite
命令切换到指定环境,之后就可以使用该环境下的各种依赖和软件包了。比如说,切换到 base
环境之后,可以通过输入 python
命令直接和当前环境下的 Python 解释器交互。
conda activite base
使用 deactivate
命令离开当前的 base
环境。
conda source
创建环境与管理依赖
Anaconda 将各种科学计算包放到了 base
环境下。尽管原则上,所有 Python 项目都可以只运行在这一个 base
环境,但是多个项目可能会依赖同一个软件包的不同版本,从而导致依赖冲突。因此,在实际开发中,我们总会为每一个 Python 项目单独创建一个 conda 环境:
conda create [pkg1[=v1]] [pkg2[=v2]]
可以在环境名后面罗列出所需要的一个或多个软件包,以空格区分开,每个软件包都可以显式地注明版本号。比如,我们为新项目创建一个名为 py3env
的环境,并安装 Python 以及 pandas
包,同时,将 Python 的版本显式指定为 3.8。
conda create -n py3env python=3.8 pandas
如果不显式指定 Python 的版本,那么 conda 默认选择和 Anaconda 同步的 Python 发行版本。
如果引入的包还依赖其它更基础的包,conda 会将它们也一同安装到环境下。对于一些 Anaconda 本身不提供的软件包,conda 需要联网到镜像源中下载。由于默认的镜像源在国外,因此可能会存在下载速度慢甚至下载失败的现象,这是任何库管理工具 ( 无论 conda,yum,docker,sdkman! 还是 maven ) 都普遍存在的一个问题。
对于国内的开发者而言,使用清华大学提供的镜像源是一个不错的选择。
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
可以通过 config
确认 conda 当前的镜像源配置:
conda config --show-sources
可以通过 search
令 conda 根据当前的镜像源配置寻找可用的软件包。默认情况下 conda 会根据给定的名称进行模糊匹配,也可以通过 --full-name
选项进行精确匹配。
conda search
conda search --full-name
可以通过 clone
的方式令 conda 根据已有的环境复制出一个新环境:
conda create -n --clone
可以通过 install
安装第三方软件包。默认情况下安装到当前环境,也可以通过 --name
选项指定安装环境。
conda install [pkg[=ver2]] ...
conda install --name [pkg[=ver2]] ...
当某些软件包不再被需要时,可以简单地上述的命令改成 remove
进行卸载。当某个环境已经不再需要时,可以通过 conda env remove
删除。conda 不能删除当前正激活的环境,需要先 conda deactivate
退出。
conda env remove -n
在 Windows 系统下,在安装 Anaconda 时还会附带名为 Anaconda Navigator 的软件。它提供了一个图形化 conda 操作界面,允许用户以简便的方式实现上述的各种操作;这降低了用户的上手成本。
导出 / 导入 conda 环境
Python 项目对软件包的版本 非常敏感。当我们最终决定将某个开源的 Python 项目上传到 Github 时,应当明确地声明项目的各种依赖包以及版本号信息,否则其他人将很难顺利地运行我们的代码。
首先,conda 本身可以通过将环境整体导入导出的方式解决问题。现在假设已经进入到了 py3env
环境下,我们可以通过以下命令将当前环境的各种依赖信息以文本形式导出,注意拓展名必须是 *.txt
,*.yaml
,*.yml
的其中一个。
conda env export > imports.yml
再假设在另一个机器安装好了 conda。在另一个机器创建新环境时可以通过 -f
选项将依赖文件所记载的环境名,依赖包及版本号,镜像源全部导入进来。
conda env create -f imports.yml
第二种方式是通过 pip 工具导入 / 导出项目依赖 ( 比如有些机器不用 conda 管理环境 )。pip 是一个专门下载并管理 Python 依赖库的工具,conda 总是会将它内置到各个环境下。每个环境下的 pip 只管理当前环境的依赖。使用 pip 导出的依赖文件约定上以 requirements.txt
来命名。
pip list --format=freeze > requirements.txt
网上大部分推荐的是 pip freeze 命令。在此不直接这么做的原因,见:pip freeze 导出含有路径 (@ file:///) 问题小记-CSDN博客
同样地,这份文件可以被其它环境下的 pip 工具导入进去:
pip install -r requirements.txt
仅从下载依赖这一功能上看,conda 和 pip 有一点重合,但是使用 conda 进行依赖管理要比 pip 更加方便。只是对于部分 Python 依赖,conda 可能无法安装,这时候可以再去尝试用 pip 进行安装。
开发环境
PyCharm: the Python IDE for Professional Developers by JetBrains
环境的问题解决之后,下一步就是挑选一个趁手的 IDE 开发项目了,这里选择 Jet Brains 公司的 PyCharm。在使用 PyCharm 创建新的工程时,选择 New Conda environment
,然后将本机安装好的 conda 设置为解释器 ( interpreter ) 。
我们不需要事先手动通过 conda 创建环境,PyCharm 会借助本地的 conda.exe
替我们搞定。默认新创建的环境名称和项目名保持一致。
随着开发的进行,可能需要进一步引入更多的依赖。我们可以在 PyCharm 的 Settings 设置中直接进行对 conda 环境进行包管理工作:
在此之后,我们可以专注于项目工程,在大部分情况下无需再手动通过终端与 conda 交互了。
作者:花花子 来源:稀土掘金