使用conda-build构建包并上传至anaconda.org

为什么要写这篇文章:
因为实验室有把自己写的工具上传到conda,其他用户可以直接用conda install -c ChannelName PkgName的方式下载并使用。但是不管是中文站点还是英文站点在这方面的解释都很少,经历了各种错误和失败,最后终于上传成功,解决的方法其实也很简单,主要是没有一个详细的教程,在这里分享我打包的过程,帮助有这方面需求的朋友们少走弯路。
对于第一次使用conda-build的朋友们,这里引用官方文档中的话:

Conda recipes are typically built with a trial-and-error method. Often the first attempt to build a package fails with compiler or linker errors, often caused by missing dependencies. The person writing the recipe then examines these errors and modifies the recipe to include the missing dependencies, usually as part of the meta.yaml file. Then the recipe writer attempts the build again and, after a few of these cycles of trial and error, the package builds successfully.

精简点说:conda-build通常是试错法来建包的,所以经常会因为一些如编译器或者依赖项的错误,而导致构建失败。请在初学者在构建包的过程中保持耐心,仔细排查错误,多看几次本教程或者官方文档,深入理解之后一定可以成功构建并上传自己的包。


1. 用到的工具

必要工具为conda-buildanaconda-client,部分用户可能需要setuptools。即:

conda install conda-build
conda install anaconda-client
conda install setuptools
  • conda-build

    conda-build可以将 package 打包为 conda 可以识别的包,以下为官网介绍:

    Conda-build contains commands and tools to use conda to build your own packages. It also provides helpful tools to constrain or pin versions in recipes. Building a conda package requires installing conda-build and creating a conda recipe. You then use the conda build command to build the conda package from the conda recipe.
    You can build conda packages from a variety of source code projects, most notably Python. For help packing a Python project, see the Setuptools documentation.

    简单翻译
    conda-build包含使用conda来构建自己包的命令和工具,同时提供了限制或者指定recipes中其他包版本的工具。使用时需要首先安装conda-build,并创建conda recipes。然后使用conda-build的命令由conda recipes构建conda包
    用户可以使用各种源码来构建conda包,打包python项目时也可以参阅Setuptools

  • anaconda-client

    anaconda-client工具的使用较为简单,主要用于将构建好的包上传至anaconda.org。只需要注册一个anaconda的账号即可。注册及登录等详情见附录。

  • setuptools

    setuptools用于建立,以下官方介绍:

    Setuptools is a fully-featured, actively-maintained, and stable library designed to facilitate packaging Python projects.
    It helps developers to easily share reusable code (in the form of a library) and programs (e.g., CLI/GUI tools implemented in Python), that can be installed with pip and uploaded to PyPI.

    简单翻译
    Setuptools 是一个功能齐全、积极维护且稳定的库,旨在促进 Python 项目的打包。
    它帮助开发人员轻松共享可重用代码(以库的形式)和程序(例如,用 Python 实现的 CLI/GUI 工具),可以使用 pip 安装并上传到 PyPI。


2. 准备构建conda包需要的文件

我们以HiCAT工具为例,源码放在/path/HiCAT中,我们在同级目录需要创建两个文件,分别是build.shmeta.yaml。文件结构如下:

-path/
  -HiCAT/
    -stringdecomposer/
    -testdata/
    -HiCAT.py
    -HiCAT_HOR.py
    -README.md
    -run_test.sh
    -visualization.py
  -meta.yaml
  -build.sh

下面分别介绍三个文件或文件夹(HiCAT/meta.yamlbuild.sh)的作用。

  • HiCAT/文件夹

    HiCAT文件夹中存放了所有源码以及README.mdrun_test.sh文件。其中run_test.sh为构建conda包时,conda运行测试的脚本或命令(也可以是run_test.py)。

  • meta.yaml文件

    meta.yamlconda-build打包的配置文件,它告诉conda-build如何将HiCAT/目录下的文件打包。文件内容为:

    package:
      name: hicat
      version: 1.0.0
    
    source:
      path: /path/HiCAT
    
    build: 
      number: 0
      entry_points: 
        - hicat = HiCAT:main
    
    requirements: 
      bulid: 
        - python >=3.9
        - setuptools
        - make
      run: 
        - python >=3.9
        - biopython =1.79
        - setuptools =61.2.0
        - joblib =1.1.0
        - numpy =1.22.3
        - pandas =1.4.0
        - python-levenshtein =0.12.2
        - python-edlib =1.3.9
        - networkx =2.7.1
        - matplotlib =3.5.1
    
    test: 
      source_files: 
        - run_test.sh
        - testdata/*
        - HiCAT.py
        - HiCAT_HOR.py
        - stringdecomposer/*
      imports: 
        - HiCAT
        - HiCAT_HOR
      commands: 
        - hicat -i ./testdata/cen21.fa -t ./testdata/AlphaSat.fa
    
    about: 
      home: https://github.com/865699871/HiCAT
      license: GPLv2
      summary: "HiCAT: Hierarchical Centromere structure AnnoTation Tool"
      description: "Advanced long-read sequencing technologies have revolutionized genome assembly, unlocking the complex region centromere and signaling the new stage in genomics research. The new computing problems generated by these new areas, like centromere annotation problem, required novel bioinformatics methods. Here, we proposed HiCAT, a generalized computational tool based on hierarchical tandem repeat mining (HTRM) method to automatically process centromere annotation."
    

    meta.yaml文件主要分为六个部分packagesourcebuildrequirementstestabout,每个部分由其名称、冒号和空格组成(如package + : + 空格),其中packagesource为必填信息,剩余为可选项,各个功能将依次介绍。

    1. package

      指明包的基本信息:

      • name:包名。
      • version:包的版本。
    2. source

      指明package的来源,即用来构建包的源码。有两种形式,既可以是本地路径,也可以是远端路径。

      本地路径:

      • path:本地源码路径,上面的例子为HiCAT/的文件夹。

      远端路径(举例):

      source:
        url: https://github.com/your_github_path/HiCAT.tar.gz
        md5: 99db123456789123456789123456789
      
      • url:远端路径。
      • md5:因为使用的是远端路径,所以需要提供md5校验码验证文件完整性。
    3. build

      指明此次build的基本信息,用来区分不同批次打包的文件,体现在打包成功后的文件名中。同时也在这个部分为包添加命令行工具。

      • number:构建成功后包文件名信息中的最后一位,该数字默认为 0。(如hicat-1.0.0-0.tar.bz2中的-0)。

      • entry_points:为包添加命令行工具,形式为CommandName = Dict.Script:EntryFunction,这里是hicat = HiCAT:main。例如:
        HiCAT.py中包含了main函数,调用其方法为python HiCAT.py -i ./testdata/cen21.fa -t ./testdat/a/AlphaSat.fa
        当添加了entry_points时,conda-build在建立成功后的压缩包中的bin/文件夹中,创建一个hicat文件,安装后可以直接使用hicat -i ./testdata/cen21.fa -t ./testdata/AlphaSat.fa进行调用。

        注意:如果构建的是带有__init__.py的包,则应使用setuptools工具,并将entry_points写入setup.py

    4. requirements

      requirements包含两个部分,分别叫buildrun,分别指明包在构建运行过程中所依赖的其他包或工具。形式为package >=1.0,其包名和符号中间间隔一个空格。

      • buildconda-build 在构建包时,运行 build.sh(build)时需要的依赖。这里需要python,setuptoolsmake
      • run: 运行包的时候需要的依赖。
    5. test

      当包建立成功后,conda-build将执行此环节。conda-build首先创建一个临时环境,在这个环境下安装构建好的包,同时安装run所需要的依赖。随后检索临时环境下是否包含run_test.[py,sh,bat等]文件,如果有则自动运行此文件。

      • source_files:指明运行测试时需要用到的文件,工作路径为/path/HiCAT/。这个部分中首先包含了run_test.sh,其次包含了其他python脚本,以及测试时需要用到的数据(testdata/*表示包含此文件夹及其内部的所有文件)。
      • importsconda-build将自动构建脚本,使用import命令进行测试。
      • commandsconda-build将运行命令行进行测试。
    6. about

      这部分主要表明这些包的相关信息,这些信息会自动显示在这个包的主页中。可以添加很多信息,以下仅作举例:

      • home:主页url
      • license:许可证类型
      • summary:简述
      • description:详细描述
  • build.sh文件

    build.sh脚本中包含编译及安装包的方法。
    以下解释中需要用构建时生成的文件路径来辅助阐述,如果不理解的话可以看完第四部分构建过程,再回头把这部分看一遍

    • 如果构建的是python(标志为带有__init__.py文件),可以使用setuptools自动完成编译和安装,成功后setuptools会生成.egg文件,conda-build会自动将其复制到lib/python3.X/site-packages/中。所以命令为:

      python setup.py install 
      

      setuptools的详细用法在附录给出,或者也可以在网上自行查阅。

    • 如果构建的是由脚本等组成的工具,则需要自行将脚本复制到相应的文件夹bin/

      mkdir -p $PREFIX/bin
      cp -rf $SRC_DIR/stringdecomposer $PREFIX/bin
      cp $SRC_DIR/HiCAT.py $PREFIX/bin
      cp $SRC_DIR/HiCAT_HOR.py $PREFIX/bin
      cp $SRC_DIR/visualization.py $PREFIX/bin
      cd $PREFIX/bin/stringdecomposer
      make  
      

      这里将stringdecomposer文件、HiCAT.pyHiCAT_HOR.pyvisualization.py复制到包中的bin/文件夹中。

3. 构建conda包

准备好三个文件后,就可以开始构建了

cd path
conda build .

构建成功后,压缩包会存放在/home/user/miniconda/envs/EnvName/conda-bld/linux-64/hicat-1.0.0-0.tar.bz2位置。

4. 构建过程

  1. 读取 recipe 文件夹中的 meta.yaml 文件。
  2. 创建本次打包的临时工作目录,如 hicat 是 /home/miniconda3/envs/Your_Env_Name/conda-bld/hicat_1667742916085/ 。再将 source 文件夹下内容放在hicat_1667742916085/work/。文件结构如下:
    -work/
      -stringdecomposer/
      -testdata/
      -HiCAT.py
      -HiCAT_HOR.py
      -README.md
      -run_test.sh
      -visualization.py
    
  3. 创建一个用于 build 的环境,如 hicatbuild 环境所在目录为 hicat_1667742916085/_h_env_placehold_placehold_placehold...
  4. build 环境中安装运行 build.sh 所需依赖,即 meta.yaml 文件 requirements 部分中 build 下所需的依赖。
    hicat的 为 pythonmakesetuptools
  5. hicat_1667742916085/work/ 工作路径下运行 build.sh 脚本(注意 build.sh 的依赖环境与工作路径不同),即:
    mkdir -p $PREFIX/bin
    cp -rf $SRC_DIR/stringdecomposer $PREFIX/bin
    cp $SRC_DIR/HiCAT.py $PREFIX/bin
    cp $SRC_DIR/HiCAT_HOR.py $PREFIX/bin
    cp $SRC_DIR/visualization.py $PREFIX/bin
    cd $PREFIX/bin/stringdecomposer
    make  
    
  6. build.sh 脚本运行完成后,conda-build 会分析 work/ 中的文件并打包生成压缩包,同时删除 build 环境。如 hicat 打包完成后会在 /home/miniconda3/envs/Your_Env_Name/conda-bld/linux-64/ 下生成压缩包 hicat-1.0.0-0.tar.bz2
  7. 如果meta.yaml文件中包含test部分,则会运行测试。
    1. 创建一个用于 test 的环境,如 hicattest 环境所在目录为 hicat_1667742916085/_test_env_placehold... 。在 test 环境中安装 package 测试所需的依赖,即 meta.yaml 文件 requirements 部分中 run 下所列的依赖。
    2. 创建 work/test_tmp/ 文件夹作为 test 的工作路径,将 test 所需的脚本 run_test.sh 及数据复制到此文件夹中,即 meta.yaml 文件 test 部分中 source_file 下所列的文件。
    3. 运行 run_test.sh ,因为工作路径为 work/test_tmp/ ,所以输出结果也存放在 test_tmp/ 中。
    4. 如果测试成功,则会返回信息TEST END
      如果测试失败,则将/home/miniconda3/envs/Your_Env_Name/conda-bld/linux-64/hicat-1.0.0-0.tar.bz2压缩包转移到conda-bld/broken下。
  8. 如果没有测试或测试成功,conda-build 会删除缓存目录。
    如果测试失败,conda-build 会保留/home/miniconda3/envs/Your_Env_Name/conda-bld/linux-64/hicat_1667742916085 及目录下所有内容,以便开发者可以随时查看,寻找失败原因。

5. Conda-build打包完成后内容

hicat-1.0.0-0.tar.bz2文件结构:

-hicat-1.0.0-0.tar.bz2/
  -info/
    -test/
      -testdata/
      -stringdecomposer/
      -run_test.sh
      -run_test.py
      -HiCAT_HOR.py
      -HiCAT.py
    -recipe/
      -HiCAT/
      -meta.yaml.template
      -meta.yaml
      -conda_build_config.yaml
      -build.sh
    -其他文件
  -bin/
    -stringdecomposer/
    -visualization.py
    -HiCAT_HOR.py
    -HiCAT.py
    -hicat
  -lib/
    -...(hicat-1.0.0-0.tar.bz2中没有lib文件,这里做占位)

lib/bin/hicatbuild.sh 运行创建的文件夹。使用setuptools会将安装包放在lib/中,而工具类脚本则需要在build.sh中自行使用命令将脚本存放在bin/文件夹中(如果使用entry_points,则这个文件也会放在bin/中)。

  • 文件夹内的文件在运行 conda install hicat 命令时会被复制到 conda 的对应文件夹中。如安装时 bin/HiCAT.py 文件会被复制到 /home/miniconda3/envs/Your_Env_Name/bin 中,lib/python3.9/site-packages/XXX.egg 文件会被复制到 /home/miniconda3/envs/Your_Env_Name/lib/python3.9/site-packages/ 中(因为hicat为工具,所以没有用到setuptools,这里仅作示意)。

  • info/ 中包含了 test 部分所需的文件(info/test/),recipe 文件夹(/path/hicat/)内全部文件(info/recipe/)及 conda-build 自动生成的一些注释文件(-其他文件)

6. Conda 上传打包好的包

登录 anaconda

 $ anaconda login

上传

 $ anaconda upload /home/ght/miniconda3/envs/HiCAT/conda-bld/linux-64/hicat-1.0.0-0.tar.bz2

附录

1. 如何注册anaconda.org账号并上传

  • 打开anaconda.org,注册账号密码。需要注意的是anaconda.org不需要邮箱验证,很方便。

    anaconda注册.png

  • 随后命令行中输入命令,再根据提示填写账号和密码进行登录

    anaconda login
    
  • 登录后,每当conda打包成功之后,anaconda-client会自动上传到anaconda.org。如果需要关闭自动上传功能,输入以下命令

    conda config --set anaconda_upload no
    
  • 需要上传至anaconda.org时,可以手动上传

    anaconda upload /yourPath/pkgName.ver.tar.gz2
    

参考
在 Conda 上发布 python 包_浓香鸭腿面的博客-CSDN博客_conda发布
构建conda包并上传至anaconda_jeffoverflow的博客-CSDN博客
conda build 系列教程・deepmd 的构建②|libtensorflow_cc - 知乎 (zhihu.com)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容