以前から自分で作成したPythonパッケージをPyPIにリリースしていた。

https://note.yu9824.com/howto/2021/07/23/register-PyPI.html

したがって、pip install <package-name>とすることでインストールできた。しかし、この度conda install -c conda-forge <package-name>でインストールしたいという要望をいただいたのでanaconda cloudにパッケージをアップロードする方法を学んだ。

https://github.com/yu9824/kennard_stone/issues/5

このときの手順をメモした。

環境

M1チップ搭載のMacbook Air 2020を使用。

% sw_vers
ProductName:	macOS
ProductVersion:	12.3.1
BuildVersion:	21E258

しかし、いくつか問題が生じたので、continuumio/miniconda3: 4.11.0のAMD版のイメージを使用して環境を構築し、この中で実行を行った。

詳細は以下。

https://note.yu9824.com/error/2022/05/06/conda-skeleton-error.html

経緯

PyPIにパッケージをリリースしていれば比較的簡単にアップロードできるようになっている。

このやり方に関して公式が説明してくれているサイト(英語)がある。

日本語では、この記事でパッケージをリリースする方法が書かれている。しかしこれはWindowsであり、少し状況が異なる。

したがって、自分で試行錯誤した結果をメモする。

基本的なやり方

やり方の概略は以下。

  1. ターミナル上でconda activate baseなどを実行し、base (環境によってはroot) 環境に入る
  2. conda install conda-buildをして、conda-buildパッケージをインストールする
  3. conda skeleton pypi <package-name>を実行し、レシピを作成する
  4. レシピをもとにパッケージを作成する
  5. Anaconda cloudにアップロードする

ちなみに、Anacona cloudにアップロードするとき、自分自身のチャンネルにアップロードする場合とconda-forgeチャンネルにアップロードする方法とがある。conda-forgeチャンネルにアップロードする場合は、レシピを渡せば4.と5.をやってもらえる。

パッケージの作成も正しいレシピが作成できていれば簡単なので肝はレシピの生成段階であると個人的には考えている。

なお、<package-name>と書いた部分はご自身の行いたいパッケージの名前に変えて実行していただきたい。

base環境に入る

(base)....@...となっていれば問題ない。インストールして、特に設定をいじっていなければ自動で入る設定になっている。

なお、base環境に勝手に入らないようにする設定もある。詳しくは以下。

https://note.yu9824.com/howto/2022/04/15/migration-my-setup-macbook.html#miniforge

conda-buildパッケージをインストールする

以下のコマンドをターミナルで実行し、インストール。

conda install conda-build

このパッケージはbase (root) 環境でないとインストールできない(らしい)。

conda skeletonコマンドを実行し、レシピを生成

正式なやり方

conda skeleton pypi <package-name>

このコマンドにより、パッケージ生成のためのレシピが生成される。

このときの注意点

<package-name>のディレクトリがカレントディレクトリの直下に生成されるので、同じ名前のディレクトリがないことを確認したのちに実行する必要がある。そうでないとエラーを生じる。

特に重要なのはmeta.yaml。必要であればここを書き換える必要がある。

自分は生成されたレシピを以下のように書き換えた。

https://github.com/conda-forge/kennard-stone-feedstock/blob/main/recipe/meta.yaml

conda-skeletonが失敗するとき

これについて以下の記事で検討した。

https://note.yu9824.com/error/2022/05/06/conda-skeleton-error.html

端的に言えば、Python 3.7以上もしくは、ARMチップである場合に正常に動作しない。さらにパッケージ名に”-“(ハイフン)が入っている場合も問題が生じる場合がある。

これを解決するためにdockerコンテナ上にPython3.6、AMDプロセッサ環境を構築し、かつ”-“を処理するシェルスクリプトを書いて対応した。

追記(より簡単な解決方法)

conda-skeletonの失敗に関する検討記事でも言及したが、これはこのような面倒な作業などする必要がなく、grayskullパッケージを使用することで解決できる。

grayskullはconda-forgeチャンネルから簡単にダウンロードできる。

conda install -c conda-forge grayskull

あとは、以下の通りgrayskullコマンドを実行すれば自動的にmeta.yamlファイルを生成してくれる。

grayskull pypi <package-name>

レシピをもとにパッケージを作成

これ以降の工程に関しては、自分のチャンネルでインストールしたいか、conda-forgeチャンネル経由でインストールできるようにしたいかでやり方が異なる。

conda-forgeチャンネルの場合はこちら

https://note.yu9824.com/howto/2022/05/07/conda-package-release.html#conda-forgeチャンネルの場合

ここには自分のチャンネルの場合を示す。この場合は自分で作成する必要がある。

conda build <package-name>

依存するパッケージがconda-forgeチャンネル経由でインストールする必要がある場合は、以下のようにチャンネルを指定しても良い。

conda build -c conda-forge <package-name>

作成の成功可否を確認する方法

適当な仮想環境を新しく作成して、--use-localオプションを付してconda installを実行することで確認できる。正しく作成が行うことができていれば、インストールすることができる。

たとえば、以下のように行う。

conda create -n test    # testという名前の仮想環境を作成。名前はなんでも良い。
conda activate test     # 先ほど作成した仮想環境に入る。
conda install --use-local -c conda-forge <package-name> # ローカルのレシピを使用してパッケージをインストールする。チャンネルはconda buildを実行したときに使用したチャンネルを指定すると良い。

テストに成功したら、以下のコマンドでbase環境に戻っておく。

conda deactivate
conda activate base

Anaconda cloudへのアップロード

事前にAnaconda cloudでアカウントを登録しておく必要がある。

現在base環境にきちんといることを確認して以下のコマンドを実行し、anaconda-clientパッケージをインストールする。

conda install anaconda-client

インストール完了後、以下のコマンドを実行してターミナル上で先ほど登録したAnaconda cloudアカウントにログインする。

anaconda login

求められる通りにユーザー名とパスワードを入力する。

その後、conda buildしたときに生成したXXX.tar.bz2を探し、それを以下のコマンドでアップロードする。

anaconda upload /path/to/<package-name>-<version>-XXXX.tar.bz2

私の環境ではconda-bldディレクトリの下にアーキテクチャごと(もしくはnoarch)に生成されていた。そのファイルのパスを指定してuploadすることで完了する。

アップロードできたかはhttps://anaconda.org/<Username>/<package-name>にアクセスし、正しくアップロードされていることが確認できればOK。

conda-forgeチャンネルの場合

レシピ生成の工程(meta.yamlの生成)まで共通。

  1. base環境に入る
  2. conda-buildパッケージをインストールする
  3. conda-skeletonコマンドを実行し、レシピを生成

— ここまで共通 —

  • conda-forge/staged-recipesをforkし、pull
  • ブランチを切って、レシピを移動し、commit
  • pushしてpull requestを送る
  • チェックリストやレビュー、テストの結果を元に修正を加える

conda-forge/staged-recipesをforkし、pull

以下のレポジトリをforkする。

https://github.com/conda-forge/staged-recipes

これをpullする。

git pull git@github.com:<your-github-id>/staged-recipes.git

ブランチを切って、レシピを移動し、commit

先ほどpullしたリポジトリに移動する。

cd /path/to/staged-recipes

次に、以下のコマンドなどを利用して新しいブランチを作成した上で、そのブランチに移動する。

git checkout -b <package-name>

その後、レシピ(meta.yaml)をリポジトリ内の/recipes/<package-name>/meta.yamlに移動させる。Finderを使ってもmkdirでディレクトリを作成したあとにmvコマンドやcpコマンドを使用してもOK。

これをaddしてcommitする。

git add .
git commit -m "Add recipe of my <package-name> package."

pushしてpull requestを送る

git push origin <package-name>  # originの後ろは、新しく作成したブランチ名

そうするとgithub上にpull request(以下PR)を送るボタンが出てくるので、送る。わからない場合は、公式サイトのドキュメントが詳しい。

チェックリストやレビュー、テストの結果を元に修正を加える

PRを送ると勝手にテストをしてくれ、かつチェックリストが作成される。チェックリストに準拠するようにPRのタイトルやmeta.yamlを修正する。テストを通過し、チェックリストすべてを確認してチェックをいれると、reviewerに診てもらえる。

修正した場合、pushすれば勝手にPRに反映され、テストがスタートする。

@conda-forge/help-python to let them know that your recipe is ready for review.

How to publish a Python package on conda-forge

とあるが、自分は使わなかった。これをせずとも診てもらえた。

mergeされればめでたくpublishとなる。

参考のため、自分が実際に送ったPRを以下に示す。

https://github.com/conda-forge/staged-recipes/pull/18779

参考

関連

https://note.yu9824.com/error/2022/05/06/conda-skeleton-error.html

https://note.yu9824.com/howto/2021/07/23/register-PyPI.html