自作モジュールをPyPI(Python Package Index)にアップロードしてpipでインストールする

投稿日 2023年2月7日 >> 更新日 2023年6月22日

概要

自作したモジュールをPyPI(Python Package Index)にアップロードし、アップロードされたリポジトリをpipでインストールします。

TestPyPIでテストする際の注意点についても説明します。

尚、この記事ではPyPIにアップロードする手順などを中心に実装していくので、アップロードに至るまでのファイル群や自作モジュールについて以下の記事をご参照ください。

環境開発&使用ライブラリ

開発環境
Windows Subsystem for Linux 1
Python 3.7.0
pip 23.0
使用ライブラリ ライセンス
build==0.10.0 MIT
twine==4.0.2 Apache Software License

PyPI(Python Package Index)にアカウントを作成する

PyPIとは「プログラミング言語Python用のソフトウェアのリポジトリです。」と公式で説明されており、Pythonをインストールすると標準で搭載されているパッケージマネージャーツールです。

「pip」コマンドを使用することによって、PyPIにアップロードされているパッケージ(リポジトリ)をローカル環境下にインストールできることは馴染み深いと思いますが、この記事では自作モジュールをPyPIにアップロードしていきます。

その前にこちらのPyPI公式サイトからアカウントを作成して登録する必要があるので、アカウントを持っていない場合は以下の手順で進めて下さい。

公式サイトにアクセスしたら、画面右上の「登録」をクリックします。

画面が以下のように遷移したら、必要事項を入力します。

「名前」や「ユーザー名」は公開プロフィールとして公開され、「ユーザー名」に限っては、一度登録したら変更できないので注意が必要です。

必要事項を記入したら、PyPIから入力したメールアドレス宛に「確認」メールが送信されます。

以下はPyPIからのメールを一部抜粋した内容です。

# PyPIからのメール一部抜粋

...

このリクエストを進めるには、このリンクをクリックしてメールアドレスを確認してください。

このリンクの有効期限は72時間です。

...

送られてきたメールの本文で「このリンクをクリックしてメールアドレスを確認してください。」をクリックするとそのアドレスに対して「確認済み」となります。

「ログイン」してから「アカウント設定」を開くと、以下の項目にある緑の確認済みというマークが添えられます。

これでPyPIに自作モジュールをアップロードすることができるようになります。

APIトークンの作成

自作モジュールをPyPIにアップロードする際には、ユーザー名やパスワードでの認証を通過してからPyPIに保存されます。

しかしセキュリティの観点から、パッケージごとのAPIトークンを作成して認証を行うことが推奨されています。

自分のアカウント上にパッケージが存在していなければまだ必要無いと思いますが、1つ以上のパッケージを保持していればAPIトークンを作成する方が良いと思います。

APIトークンの作成は、まず自分のアカウントを開き、「アカウントの設定」をクリックします。

以下の画面に遷移されたら、下方にスクロールして「APIトークンの作成」をクリックします。

以下のように「トークン名」と「スコープ」というフォームが表示されます。

「トークン名」はプロジェクトに関する命名をし、「スコープ」ではどのパッケージを紐づけるかを選択します。

パッケージが無い場合は「全プロジェクト」となります。

「トークンの追加」をクリックすると「APIトークン」を発行されるのでコピーして大事に保管しておきます。

PyPIに自作モジュールをアップロードする

自作モジュールをアップロードするには、自身で構築したパッケージに対してビルドを行い配布用パッケージを作成する必要があります。

以下は自作モジュールのビルドが終わり配布用パッケージが作成された後のディレクトリ構造です。

my_project
├── LICENSE
├── README.md
├── dist # 配布用パッケージが格納されたディレクトリ
│   ├── site_requests-0.0.6-py3-none-any.whl
│   └── site_requests-0.0.6.tar.gz
├── pyproject.toml
├── src
│   └── site_requests
│       ├── __init__.py
│       └── example.py
├── tests

ビルドを行うと上記のように「dist」ディレクトリが作成されます。その中にアーカイブとして配布用パッケージ化された圧縮ファイル等が配置されます。それらのファイルをPyPIアップロードツールの「twine」を使ってアップロードするという流れです。

配布用パッケージがまだという方は以下の記事をご参照ください。

PyPIアップロードツールの「twine」をインストールします。

$ pip --version
pip 23.0

$ pip install twine

「twine」コマンドでPyPIにアップロードするパッケージを指定して実行します。

実行した際にPyPIアカウントに登録した「ユーザー名」と「パスワード」の入力が求められます。

※APIトークンでの認証は、ユーザー名を「__token__」とする

$ twine upload dist/*
Uploading distributions to https://upload.pypi.org/legacy/
Enter your username: ユーザー名
Enter your password: パスワード
Uploading site_requests-0.0.8-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 9.0/9.0 kB • 00:00 • 1.1 MB/s
Uploading site_requests-0.0.8.tar.gz
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 7.8/7.8 kB • 00:00 • ?

View at:
https://pypi.org/project/site-requests/0.0.1/

アップロードの実行中に以下のような「WARNING」が表示される場合があります。

WARNING  Error getting password from keyring
         Traceback (most recent call last):
           File "/home/kenno/.pyenv/versions/3.7.0/lib/python3.7/site-packages/twine/auth.py", line 74, in get_password_from_keyring
             return cast(str, keyring.get_password(system, username))
           File "/home/kenno/.pyenv/versions/3.7.0/lib/python3.7/site-packages/keyring/core.py", line 55, in get_password
             return get_keyring().get_password(service_name, username)
           File "/home/kenno/.pyenv/versions/3.7.0/lib/python3.7/site-packages/keyring/backends/fail.py", line 25, in get_password
             raise NoKeyringError(msg)
         keyring.errors.NoKeyringError: No recommended backend was available. Install a recommended 3rd party backend package; or, install
         the keyrings.alt package if you want to use the non-recommended backends. See https://pypi.org/project/keyring for details.

上記のような「WARNING」が出力されても私の環境では問題無くアップロードすることができました。

しかしこの「WARNING」を解消したいという場合は、エラー内容に従って必要なライブラリをインストールしていきます。

$ pip install keyrings.alt

$ pip freeze
...
keyring==23.13.1
keyrings.alt==4.2.0
...

これで「twine」コマンド実行中の「WARNING」エラーは解消されたかと思います。

アップロードが成功すると、以下のように自作パッケージがPyPIサイトに掲載されます。

パッケージの設定ファイルである「pyproject.toml」に記入している項目も反映されています。

# pyproject.toml

[project]
...
authors = [
    { name="your name", email="you_mail@example.com" },
]
...
license = {file = "LICENSE"}
requires-python = ">=3.7"
classifiers = [
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
]

[project.urls]
"Homepage" = "https://github.com/your-name/site-requests"
"Bug Tracker" = "https://github.com/your-name/site-requests/issues"

PyPIにアップロードした自作パッケージをインストール

アップロードされている自作のパッケージをpipインストールします。

※自作モジュール名を指定する際のアンダースコア(「_」)は、ハイフン(「-」)やドット(「.」)と同一として記入することができます。

# pip install site_requests
# pip install site.requests
$ pip install site-requests

$ pip freeze
beautifulsoup4==4.11.2
bs4==0.0.1
certifi==2022.12.7
charset-normalizer==3.0.1
idna==3.4
requests==2.28.2
site_requests==0.0.1
soupsieve==2.3.2.post1
urllib3==1.26.14

「pip show」コマンドで指定したパッケージの詳細情報を取得できます。

$ pip show site-requests
Name: site_requests
Version: 0.0.1
Summary: A small site requests package
Home-page:
Author:
Author-email: your name <you_mail@example.com>
License: MIT License

        Copyright (c) 2023 The Python Packaging Authority

        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.

        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
Location: /mnt/c/Users/Documents/test/venv/lib/python3.7/site-packages
Requires: bs4, requests
Required-by:

TestPyPIで依存先パッケージがインストールされない理由

TestPyPIで自作モジュールのアップロードをテストする際に知っておいたら時短になる事を説明します。

恐らくこちらの「Python公式 のプロジェクトをパッケージングする」の手順でパッケージ化された方は、TestPyPIを利用するかと思います。

TestPyPIは、PyPIさながらの方法でアップロードしてインストールを行うことができますが、自作モジュールに依存しているサードパーティがある場合は注意が必要です。

例えば今回「PyPI」にアップロードされた自作モジュールには「requests」と「bs4」というサードパーティを使用しており、pipでインストールする際は依存関係にあるサードパーティも一緒にインストールされるように「pyproject.toml」に設定しています。

# pyproject.toml

[project]
...

dependencies =  [
    "bs4 == 0.0.1",
    "requests >= 2.28.2",
]
...

PyPIにアップロードされているライブラリとTestPyPIにアップロードされているライブラリは異なるので、上記の設定ファイルでビルドを行ったあとにTestPyPIへアップロードし、pipでインストールすると以下のようにエラーが発生してしまいます。

$ pip install -i https://test.pypi.org/simple/ site-requests==0.0.1
...
ERROR: Could not find a version that satisfies the requirement bs4==0.0.1 (from site-requests) (from versions: none)
ERROR: No matching distribution found for bs4==0.0.1

「requests」や「bs4」といったパッケージは本番サイトのPyPIのみに存在しておりTestPyPIにアップロードされたパッケージは時間が経つと自動削除されてしまうみたいなので、依存関係にあるパッケージがある場合は注意が必要です。

それでは以上となります。

最後までご覧いただきありがとうございました。

一覧へ戻る