Pythonは、オブジェクト指向プログラミング言語の一つであり、多くの場面で使われる汎用言語です。Pythonを使うことで、簡単かつ効率的にアプリケーションやツールを開発することができます。
Pythonで開発したアプリケーションやツールを他の人が使えるようにするためには、パッケージ化が必要です。
そこで、本記事では、Pythonパッケージ開発の入り口となる「setup.py」の使い方について初心者向けに解説します。
Pythonを勉強する時、何から勉強するか分からず、挫折します。初心者でも、中級者でも、レベルに合わせた勉強方法を分かりやすくまとめています。
環境の準備
Pythonパッケージ開発に取り組む前に、まずPythonの環境構築を行う必要があります。
ここでは、Pythonのインストール方法、仮想環境の作成方法について解説します。正しい環境の構築を行うことで、安全で効率的なPythonパッケージ開発を行うことができます。
Pythonのインストール
Pythonをインストールする方法は、OSによって異なりますが、以下に一般的な手順を簡単にまとめます。
- 公式サイトからインストーラーをダウンロードする Pythonの公式サイトから、自分のOSに対応したインストーラーをダウンロードします。
- インストーラーを実行する ダウンロードしたインストーラーを実行し、表示される指示に従ってインストールを進めます。
- PATHを設定する(オプション) PATHを設定することで、コマンドラインからPythonを直接実行できるようになります。Windowsの場合は、環境変数の「Path」にPythonのインストール先を追加します。macOSやLinuxの場合は、.bash_profileや.bashrcなどのシェルスクリプトに、export PATH=$PATH:/usr/local/bin/python(インストール先によって異なります)を追記します。
以上がPythonの一般的なインストール手順ですが、OSや環境によってはさまざまなインストール方法があります。必要に応じて、公式ドキュメントなどを参照してください。
仮想環境の作成
仮想環境を使用することで、異なるプロジェクトで使用されるPythonのバージョンやライブラリーを分離し、衝突を避けることができます。
例えば、プロジェクトAがPython 3.7とDjango 2.2で、プロジェクトBはPython 3.9とDjango 3.1の場合、仮想環境を作成すると、互いに影響しないようにできます。
また、他の開発者と共同開発する場合でも、各開発者でPythonのバージョンとライブラリーを統一できます。
仮想環境を作るなら、venvを使うのが一般的です。使い方は以下の記事で、詳しく解説しています。
基本的なsetup.pyの書き方
setup.pyファイルは以下のように定義します。setup()関数を使って、パッケージのメタデータを定義します。
from setuptools import setup, find_packages
setup(
name='example_package',
version='0.1.0',
packages=find_packages(),
install_requires=[
'requests',
'numpy',
],
)
setuptoolsがない場合は、以下でインストールできます。
pip install setuptools
nameはパッケージ名、versionはバージョン番号を表します。
packagesは、パッケージのリストを指定します。この例では、find_packages()を使って、自動的にパッケージを検索しています。
このように設定することで、パッケージのモジュールやサブパッケージを自動的に検出し、インストール時に一緒にパッケージ化することができます。
setup.pyを格納するディレクトリ
setup.py
は、パッケージのルートディレクトリに置くのが一般的です。
パッケージのルートディレクトリは、通常、パッケージの名前と同じ名前のディレクトリで、その下にはパッケージのモジュールやサブパッケージが配置されています。
例えば、以下のようなディレクトリ構成を持つパッケージ my_package
の場合、setup.py
は my_package
ディレクトリと同じ階層に置かれます。
my_package/
├── my_package/ # パッケージと同じ名前のフォルダを作成する
│ ├── __init__.py
│ └── module1.py
├── tests/
│ ├── __init__.py
│ └── test_module1.py
├── README.md
├── LICENSE
├── setup.py # ルートディレクトリ直下にsetup.pyを置く
└── requirements.txt
setup.pyで設定できるメタデータ一覧
以下に、setup.pyに設定できるメタデータを整理します。
メタデータ名 | 説明 | 具体例 |
---|---|---|
name | パッケージの名前 | mypackage |
version | パッケージのバージョン番号 | 1.0.0 |
description | パッケージの簡単な説明 | A simple package for doing something |
long_description | パッケージの詳細な説明 | A longer description of the package, possibly including examples |
classifiers | パッケージの分類情報 | [Programming Language :: Python, License :: OSI Approved :: MIT License] |
keywords | パッケージに関連するキーワード | mypackage, example |
author | パッケージ作者の名前 | John Smith |
author_email | パッケージ作者のメールアドレス | john.smith@example.com |
url | パッケージのURL | https://github.com/johnsmith/mypackage |
license | パッケージのライセンス | MIT |
packages | パッケージに含まれるサブパッケージのリスト | [‘mypackage’, ‘mypackage.subpackage’] |
install_requires | パッケージが依存するパッケージのリスト | [‘numpy’, ‘matplotlib’] |
entry_points | コマンドラインスクリプトのエントリーポイントを指定する | {‘console_scripts’: [‘mycommand = mypackage.cli:main’]} |
package_data | パッケージに含まれるデータファイルのリスト | {‘mypackage’: [‘data/*.txt’]} |
依存関係の設定
パッケージが依存する他のパッケージがある場合は、setup.pyに依存関係します。
install_requiresは、パッケージが依存するパッケージのリストを指定します。
例では、requestsとnumpyパッケージを依存関係として指定しています。
from setuptools import setup, find_packages
setup(
name='example_package',
version='0.1.0',
packages=find_packages(),
install_requires=[
'requests',
'numpy',
],
)
これらのパッケージがインストールされていない場合、自動的にインストールされます。
setup.pyでrequirements.txtを使う方法
しかしながら、Pythonでモジュールの依存関係を管理する時は、requirements.txtを利用するのが一般的でおすすめです。
requirements.txtの書き方など詳しい説明は以下。
setup.pyでrequirements.txtを使う場合、以下のように実装します。
from setuptools import setup, find_packages
def requirements_from_file(file_name):
return open(file_name).read().splitlines()
setup(
name='example_package',
version='0.1.0',
packages=find_packages(),
install_requires=requirements_from_file('requirements.txt'),
)
install_requiresに、requirements_from_file()関数を利用しています。これにより、setup.py
が実行されるときに、requirements.txt
に記載されている依存パッケージが自動的にインストールされます。
パッケージのビルド
Pythonのパッケージを開発する際には、パッケージをビルドする必要があります。
ビルドとは、Pythonのコードを配布可能な形式(.tar.gzや.zipなど)に変換することです。ビルドしたパッケージは、他の人がインストールしたり、再配布したりできます。
パッケージのビルド形式
パッケージのビルド形式は、「sdist」と「bdist_wheel」の2つがあります。
それぞれの特徴を表にまとめると以下の通りになります。
項目 | sdist | bdist_wheel |
---|---|---|
ファイル形式 | tar.gz、zip:ソースコードのアーカイブ | wheel(.whl):バイナリのアーカイブ |
ビルド環境 | ビルドに必要な環境があれば、どの環境でもビルド可能 | コンパイル済みバイナリが必要 |
ビルド速度 | 遅い | 速い |
インストール方法 | pip install パッケージ名 | pip install パッケージ名 |
対応OS | すべてのOSで利用可能 | 特定のOS・アーキテクチャのみ |
用途 | 主に配布用 | 開発者向け |
パッケージの配布方法としては、sdistよりもbdist_wheelを使うことが推奨されています。
これは、bdist_wheelがsdistよりも高速で、より広範なプラットフォームで動作するからです。しかし、いくつかのプロジェクトでは、パッケージのビルド方法をsdistに固定している場合があります。
パッケージのビルド方法
まずは、ビルドに必要なライブラリをインストールします。以下のコマンドを実行してください。
pip install setuptools wheel
既にインストール済みの場合、この手順はスキップできます。
パッケージのルートディレクトリにsetup.pyファイルを作成します。setup.pyファイルには、パッケージのメタ情報や依存関係、ビルド設定などを記述します。
from setuptools import setup, find_packages
setup(
name='mypackage',
version='0.1',
packages=find_packages(),
install_requires=[
'numpy',
'pandas',
],
)
既に作成済みの場合、この手順はスキップできます。
setup.pyファイルを作成したら、以下のコマンドを実行してパッケージをビルドします。
python setup.py sdist bdist_wheel
このコマンドを実行すると、distフォルダの直下に、sdist(形式はtar.gzやzip)とbdist_wheel(.whl)という2つのアーカイブファイルが作成されます。
- sdist:ソースコードのアーカイブ
- bdist_wheel:バイナリのアーカイブ
ビルドしたパッケージを別のプロジェクトで使用したい場合、以下のようにインストールができます。
# sdistのインストール方法
pip install dist/{パッケージ名}-{バージョン番号}.tar.gz
# bdist_wheelのインストール方法
pip install dist/{パッケージ名}-{バージョン番号}-py3-none-any.whl
パッケージのバージョン管理
パッケージのバージョン管理は、パッケージの開発・保守において重要な作業のひとつです。バージョン番号を上げることで、機能の追加やバグ修正を明示できます。
パッケージのバージョンは、 setup.py
ファイルの中の version
という項目で指定します。
setup.pyでバージョン番号を管理することで、パッケージのバージョンを一元管理でき、利用者はバグ修正や新機能の追加など、変更履歴の追跡がしやすくなります。
パッケージの依存関係も明確になり、パッケージのアップグレードや再インストールが簡単になります。
バージョン番号の付け方
バージョン番号は、 major.minor.patch
の3つの数字で成り立ち、major
はメジャーバージョン、 minor
はマイナーバージョン、 patch
はパッチバージョンを表します。
例えば、0.1.0
というバージョン番号は、メジャーバージョンが 0
、マイナーバージョンが 1
、パッチバージョンが 0
を表します。
バージョン番号の付け方を整理したのが、以下です。
major
:大きな変更を加えた場合。例えば、API の仕様変更や大幅な機能変更など。minor
:機能追加やバグ修正をした場合。例えば、新しい機能の追加や既存機能の改善、バグの修正など。patch
:バグ修正や文言修正をした場合。例えば、既存の機能に対する軽微な修正やドキュメントの修正など。
Semantic Versioning (セマンティック バージョニング)の紹介
Semantic Versioning (セマンティック バージョニング) は、バージョン番号のルールを統一することで、バージョン番号の解釈を簡単にするという考え方です。
Semantic Versioningには以下のルールがあります。
- 互換性が保たれない変更を加えた場合は、
major
を上げます。 - 互換性が保たれた新しい機能を加えた場合は、
minor
を上げます。
Semantic Versioningのルールに従ってバージョン番号を付けることで、他の開発者やユーザーにとってバージョン番号が意味を持ち、開発プロセスを予測しやすくなります。
テストの実行方法
テストは品質保証のために欠かせないものです。
setuptoolsを使ってパッケージをビルドし、インストールした場合、同梱されているsetup.pyファイルを利用してテストを実行することができます。
setup.pyにはtestコマンドが定義されており、このコマンドを実行することでテストが実行されます。
テストコードは通常、testsというディレクトリに格納され、unittestモジュールやpytestモジュールなどを使用して書かれます。
以下はsetuptoolsを使用したsetup.pyの例
from setuptools import setup, find_packages
import unittest
def my_test_suite():
test_loader = unittest.TestLoader()
test_suite = test_loader.discover('tests', pattern='*_test.py')
return test_suite
setup(
name='my_package',
version='0.1.0',
packages=find_packages(),
install_requires=[
'numpy',
'pandas'
],
tests_require=[
'pytest'
],
test_suite='setup.my_test_suite'
)
上記の例では、tests
ディレクトリ内の*_test.py
という名前のファイルをテストコードとして実行するように設定しています。また、tests_require
にpytest
を指定することで、テスト用のライブラリとしてpytest
を使用するように設定しています。
テストを実行するには、以下のようにsetup.pyがあるディレクトリでtestコマンドを実行します。
python setup.py test
pytestの使い方は以下で詳しく解説しています。
setup.pyのよくある質問
setup.pyのよくある質問を以下にまとめます。
Python学習におすすめのコンテンツ
現役シリコンバレーエンジニアが教えるPython 3 入門 + 応用 +アメリカのシリコンバレー流コードスタイル
Udemyの講座でPythonなら、文句なしにおすすめ
- 分かりやすい言葉や具体的なコードで工夫して説明しているので、初心者でも理解できる。
- 初心者でも挫折しないように、丁寧に詳しく手順を説明している。
- 講座内で取り扱う課題は実践的なものが多く、書籍では身につかない応用力を身につけられる。
- 情報量が多いのに、講座の進み方が速いので、一回では理解が追いつかない。
- 課題の難易度が高すぎる場合がある。
- 講師のアクセントが特殊で、聞き取りにくいと感じたことがある。
テスト駆動Python 第2版
日本語で唯一、pytestだけに焦点を当てて、詳細に書かれた書籍です。
- 日本語でpytestの全てについて、解説されている唯一の書籍
- 段々とステップアップして、深くなるので、初心者でも、中級者でも、上級者でも、学びがある
- サンプルコードには、サンプルアプリが含まれているため、実践的に学べる工夫あり
- 章末にまとめがあり、復習の役に立つ
- 第7章に「どのようなテストを書くのか」についての解説があり、テストに対する考え方が深まる
- 後半になると、かなり高度な内容になるため、初心者には難しい
- タイトルに「テスト駆動開発」と書かれているが、該当部分の記述が少なく、テスト駆動開発を知りたい人は期待外れになるかも
間違えて、第1版を買わないように注意して下さい。
おわりに
setup.pyは、Pythonパッケージの開発・配布に欠かせないツールのひとつです。
本記事では、setup.pyの基本的な使い方から応用的な使い方までを解説しました。
setup.pyの使い方を理解することで、現場での開発の幅が広がると思います。Pythonパッケージの開発・保守を行う際には、ぜひ本記事を参考にしてください。
Pythonを勉強する時、何から勉強するか分からず、挫折します。初心者でも、中級者でも、レベルに合わせた勉強方法を分かりやすくまとめています。
コメント