LoginSignup
2
3

Pythonソースコードをパッケージ化する方法(他環境へ配布を目的として)(Setup.py利用)

Last updated at Posted at 2023-09-23

概要

作成したPythonソースコードを他の環境に持って行って実行する、と言う観点でPythonでのパッケージ化の手順を説明する。

ローカルでの配布を想定し、The Python Package Index (PyPI)への登録などは論じない。

作成する配布用ファイルはWheel形式とし、作成方法は「setup.pyを用いる方法(setup()を用いる方法)」を採用する。本方法は最近では「旧手法」と呼ばれつつあるが、理解を目的に本記事ではこちらを用いる1

目的

Node.jsで言うところの「npm --save install [モジュール名]コマンドで package.json に構築しておけばOK」をPythonでどうやるのか? という疑問への回答を目的とする。

なお、上記に対してそのまま答えるのであれば「Pythonではpip freeze > requirements.txtで依存関係を出力したrequirements.txtを添えておけばよい(受け取った側は pip install -r requirements.txtする)」となる。
しかし本記事では、「Pythonでは、パッケージ形式(Wheel形式)に固めて配布し、それをインストールしてパッケージ呼び出し形式で使ってもらう」というケースへの対応を意図する。これは、Pythonの場合はこのケースへの要求が多い、ように感じられたためだ。

想定読者

  • はじめてPythonに触れる人で、しかし他の言語でのプログラミング経験は有する方
    • Python特有の部分はともかく、とりあえずHello World的な出力は悩まずにPythonでコーディングできる方
  • 自身が作成したPythonソースコードで必要な依存関係を、配布時にどう設定すればよいか?に迷っている方

動作環境(検証環境)

次の2つの環境で、サンプルコードの動作確認を実施済み。

  • Windows10
    • Python 3.11.5
  • WSL2::Ubuntu 22.04.1 LTS
    • dockerイメージ「python:3.9-alpine3.18」

特に断らない限り、「Pythonに関する操作(pip install XXXなどを含む)」はPython仮想環境に入って行うものとする(以降、「仮想環境」と略して呼称)。仮想環境の作成にはPython標準で提供されるvenvパッケージを用いる2

※「Pythonの仮想環境とはなんぞや?」と言う方は、付録章の「仮想環境とは?」を参照のこと。

サンプルコード

以下を参照のこと。

パッケージ化対象のサンプルコードの仕様

本記事では、動作に追加パッケージを必要とするケースとして、次の仕様のサンプルコードを用いる。

  • パッケージの本体はweaherforecastフォルダー
    • フォルダー内のPythonファイルopen_meteo_forecast_api.pyにて、「Open-Meteo」が提供するWeb APIを利用して指定地点の向こう1週間の1h毎の予想気温を取得する関数「get()」を提供する
  • 依存関係としてパッケージ「requests」を必要とする
    • サンプルコードに含まれるrequirements.txtは、後述の「サンプルコードの動作確認」後にコマンドpip freeze > requirements.txtにて出力したもの
  • 次のようなファイル/フォルダー構造を持つものとする
+-- requirements.txt
+-- setup.py
|   
\---weatherforecast/
    +-- open_meteo_forecast_api.py
    +-- __init__.py
    +-- __main__.py        

上記のコードの動作に必要な依存関係(追加パッケージ)をインストールするには次のコマンドのいづれかを実行する。

  • pip install requests
  • pip install -r requirements.txt

サンプルコードの動作確認

このサンプルコードの動作確認は、以下のコマンドで実施できる。
(このコマンドは、サンプルコードのルートから見て、パッケージweatherforecastを実行している。したがって package直下の__main__.pyが実行される。このフォルダー構造としている理由は、付録章の「ファイル構造に関する補足」を参照のこと)

python -m weatherforecast

上記を実行すると、東京の向こう1週間の1h毎の予想気温が出力される。

パッケージファイル(Wheel形式)の作成方法

setuptoolsモジュールで提供されるsetup()関数を用いて、Wheel形式のパッケージを作成する。慣例として、setup.py と言う名称のファイルを作成して、その中でsetup()を呼び出す。

setup.pyは、たとえば次のように記述する。

import setuptools

with open('requirements.txt') as f:
    requirements = f.read().splitlines()

setuptools.setup(
    name="weatherforecast", # Replace with your own username
    version="0.0.1",
    install_requires = requirements, # 依存関係を requirements.txt から読み込んで設定する
    entry_points={
        'console_scripts': [
            'weatherforecast=weatherforecast:main',
        ],
    },
    packages=setuptools.find_packages(), # 直下のパッケージ仕様のフォルダ名をリスト形式で全て取得
    description="sample packages by legacy-setup.py",
    # author="author",
    # author_email="sample@example.com",
    # python_requires='>=3.7',
)

ここで、パッケージの動作に必要な依存関係は、キーワード引数の表記を用いてinstall_requires=["requests==2.31.0",,,]のようにして設定する。上記のサンプルコードでは、依存関係として必要なパッケージ一覧を記載したファイルrequirements.txtを同ディレクトリに置いておき、そこから読み込む形式としている。

上記のsetup.pyファイルを作成したら、おもむろに次のコマンドでsetup.pyを引数bdist_wheelを添えて実行する(明示されていないが、setup()は関数内部でコマンドライン引数を受け取る仕様)。

pip install --upgrade pip setuptools wheel
python setup.py bdist_wheel

1行目は、パッケージ作成に必要なコマンド(パッケージ)を最新化するため&もし環境に不足していれば追加インストールするため、に実行している。
2行目のコマンド、setup.pyの実行が終わると、distフォルダーが作成されて、その配下にWheel形式のパッケージが出力される。

なお、実行途中で次のようなメッセージが表示されるが、これは「最新のPython仕様としては、setup()を用いたパッケージ作成は非推奨」としているため。今回は無視する。

SetuptoolsDeprecationWarning: setup.py install is deprecated.

Please avoid running ``setup.py`` directly.

以上で、パッケージ作成は完了。

作成したパッケージの動作確認の方法

適当な任意のフォルダーに移動し、そこに真っ新なPython仮想環境を作成する。
たとえば、次のようにする。

/home/work/downloads # python -m venv .venv_dl
/home/work/downloads # source  .venv_dl/bin/activate

作成したPython仮想環境に入っているパッケージを確認すると、次のようになっている。

(.venv_dl) /home/work/downloads # pip list
---------- -------
pip        23.0.1
setuptools 58.1.0

この環境に対して、先ほど作成したWheelファイル(*.whl)をpipコマンドでインストールする。

(.venv_dl) /home/work/downloads # pip install ../legacy/dist/weatherforecast-0.0.1-py3-none-any.whl
Processing /home/work/legacy/dist/weatherforecast-0.0.1-py3-none-any.whl
Collecting certifi==2023.7.22
  Downloading certifi-2023.7.22-py3-none-any.whl (158 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 158.3/158.3 kB 2.0 MB/s eta 0:00:00
(略)

インストールが完了後の、状態を確認すると次のようになる。

# pip list
Package            Version
------------------ ---------
certifi            2023.7.22
charset-normalizer 3.2.0
idna               3.4
pip                23.0.1
requests           2.31.0
setuptools         58.1.0
urllib3            2.0.4
weatherforecast    0.0.1

インストールしたパッケージを実行するには次のようにする。

python -m weatherforecast

この実行コマンドは「§ サンプルコードの動作確認」で説明したものと同じであり、実行結果も同じとなる。

以上ー。

(付録)

仮想環境とは?

仮想環境とは、「開発環境毎に依存関係を閉じ込める機能」とでも言うべきもの。

たとえばNode.jsであれば「npm install [パッケージA]を実行すると、そのパッケージはnpmコマンドを実行したフォルダー配下でのみ有効」であり、別のフォルダーでnpm instal [パッケージ@バージョン]コマンドを実行した場合はそれぞれのフォルダー毎に異なるバージョンのパッケージを利用する事が可能(「ローカルにインストールする」と呼称する。すべてのフォルダーで利用可能にするには「npm instal [パッケージ名] -g」コマンドで明示的に「グローバルにインストールする」必要がある)。しかしPythonでは「ローカルにインストールする」と言う概念はない。代わりに「仮想環境」を作成して入った状態では、pip install [パッケージ名]でインストールしたパッケージは、その「仮想環境」の中でのみ利用可能となる。異なる仮想環境を作ることで、異なるバージョンのパッケージをインストールして利用することが可能となる。

具体的には以下の手順で仮想環境を作成し、その中に入る。
(1つ目のコマンドの2つ目の引数は任意の識別子だが説明は省略)

python -m venv .venv

.venv\Scripts\activate
# ↑Windowsの場合。↓Linuxの場合は↓。
# source .venv/bin/activate

以降のpip installコマンド、Pythonコマンドはいずれも、この「仮想環境」での動作となる。「仮想環境」を一度作成したら、以降は.venv\Scripts\activateコマンドのみで良い。
なお、仮想環境の実態は「python -m venv .venv」を実行したフォルダ配下に作成されるフォルダ「.venv」となる。2回目以降に「仮想環境」に入るには、そのフォルダ「.venv」があるところで実行する。

「仮想環境」を抜けるには次のコマンド用いる(※別の「仮想環境」に入るには、いったん抜けること)。

deactivate

ファイル構造に関する補足

  • Pythonにおいて、「パッケージ」とは「モジュールをまとめて格納したフォルダー」のことを意味する。「モジュール」とは「Pythonファイル(*.py)」を意味する
  • 「パッケージ化する」とは「パッケージ(フォルダー)に格納したモジュール一式を、配布形式にする」と言える
  • したがって上記のように「対象の関数を定義したPythonソースコードを、フォルダー配下に格納した状態」とするのが望ましいようだ
  1. 2019年の1月のpip v19.0にて、pyproject.tomlによるパッケージインストールに対応。それ以降、少しずつ「setup()を用いたBuild」から「pyproject.tomlを用いたBuild」に置き換わりつつあるようだ。2023-09-23現在、setup()でのBuild時には「deprecated」(非推奨)というメッセージが出るようになっている。

  2. https://docs.python.org/ja/3/library/venv.html

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3