手順
ここからは、実際に手順を追ってパッケージを作ってみましょう。
※OSはWindows10、実行環境はAnaconda3で作っていきますので、MacOSなど環境が異なる場合に正しく実行されない可能性があります。
【1】パッケージのファイル構成を考える。
fortune/
├───── setup.py
├───── fortune_package/
├───── __init__.py
├───── lottery_module.py
├───── horoscope_module.py
今回の例では、fortune_package
というパッケージにlottery_module.py
とhoroscope_module.py
を入れたファイル構成で占いが出来るパッケージを作っていきます。
【2】任意のディレクトリに空のプロジェクトディレクトリを作成する。
C: Users\ユーザ名\Desktop\python files\fortune\
空のプロジェクトディレクトリを作成するディレクトリは任意なので、基本的にはどのディレクトリでも構いませんが、避けた方が無難なディレクトリもあるので説明します。
PythonとAnacondaをインストール済みの場合
この場合、サードパーティ製のパッケージをインストールした際に保存される場所は以下のバスになります。
C: Users\ユーザ名\anaconda3\Lib\site-packages
自作パッケージが完成した後、利用するためにAnacondaにインストールする必要があるのですが、無事インストール出来た際に自作パッケージが保存されるのも上記のsite-packages
になります。ここにプロジェクトディレクトリを作成してしまうと、site-packages
で作成したパッケージをsite-packages
にインストールして保存するというややこしいことになるので止めておきましょう。
普段作成したPythonモジュールを保存しているディレクトリがあればそこに、無ければDesktopに新たに自作パッケージ用のディレクトリを作成し、そこに空のプロジェクトディレクトリを作成することをおすすめします。
jupyter notebookを使って任意の場所に空のプロジェクトディレクトリを作成する方法が下記の参考文献【2】からご覧になれますのでご参考までにどうぞ。
【3】空のプロジェクトディレクトリに空のパッケージディレクトリを作成する。
C: Users\ユーザ名\Desktop\python files\fortune\fortune_package
【4】空のパッケージディレクトリに完成した複数のモジュールを入れる。
くじ引きが引けるモジュール:lottery_module
import random
def lottery():
lottery = ["大吉","中吉","小吉","末吉","凶","大凶"]
print(random.choice(lottery))
#実行結果
"""
大吉
"""
星座占いが出来るモジュール:horoscope_module
import random
def horoscope():
horoscope = [
"牡羊座","おうし座","ふたご座","かに座","しし座","おとめ座","てんびん座","さそり座","いて座","やぎ座","みずがめ座","うお座"
]
random.shuffle(horoscope)
for n,i in enumerate(horoscope, 1):
print(f"第{n}位は{i}のあなた!")
#実行結果
"""
第1位はいて座のあなた!
第2位はてんびん座のあなた!
第3位は牡羊座のあなた!
第4位はみずがめ座のあなた!
第5位はしし座のあなた!
第6位はかに座のあなた!
第7位はやぎ座のあなた!
第8位はさそり座のあなた!
第9位はおうし座のあなた!
第10位はうお座のあなた!
第11位はふたご座のあなた!
第12位はおとめ座のあなた!
"""
これら2つのモジュールを空のパッケージディレクトリに入れます。
fortune/
├───── fortune_package/
├───── lottery_module.py
├───── horoscope_module.py
ここまで来るとファイル構成はこんな感じになります。ここからパッケージをパッケージたらしめるための作業に入ります。
【5】パッケージディレクトリに__init__.py
を作成し、初期化処理を行う。
__init__.py
は、ディレクトリをパッケージとして認識するために必要なファイルです。パッケージディレクトリとして作成したfortune_package/
の直下に__init__.py
を作成することで、fortune_package/
は正式にパッケージディレクトリとして認められます。
パッケージをimportする際は、パッケージディレクトリとして正式に認められたfortune_package/
の名前を使います。import fortune_package
ですね。
__init__.py
の中身は空でも成立します。ただ、あるコードを書くことでパッケージをimport
する際により便利になるので、説明していきます。
**__init__.py
中身が空の場合**
import fortune_package as fp
#くじ引きがしたい場合
fp.lottery_module.lottery()
#星座占いがしたい場合
fp.horoscope_module.horoscope()
#実行結果
"""
大吉
"""
"""
第1位はいて座のあなた!
第2位はてんびん座のあなた!
第3位は牡羊座のあなた!
第4位はみずがめ座のあなた!
第5位はしし座のあなた!
第6位はかに座のあなた!
第7位はやぎ座のあなた!
第8位はさそり座のあなた!
第9位はおうし座のあなた!
第10位はうお座のあなた!
第11位はふたご座のあなた!
第12位はおとめ座のあなた!
"""
関数を使いたい時、モジュール名をしっかり書く必要があります。パッケージの中に使いたい関数があることは分かっているけど、どのモジュールの中にあるか分からないといった際に、いちいちモジュール名を記入しないといけないのは意外と面倒です。試しに、モジュール名を記入せずに実行してみると以下の様にエラーが吐かれます。
import fortune_package as fp
fp.lottery()
#実行結果
#lottery_module.py, line 2, in <module>
# fp.lottery()
#AttributeError: module 'fortune_package' has no attribute 'lottery'
「fortune_package
にはlottery()
という関数はない」というエラーが出ました。
モジュール名を記入しないことでパスが途切れてfortune_package
がlottery()
を見失ってしまったんですね。
さて、どうにかして関数を実行する際にモジュール名をカットする方法はないのでしょうか。あるんです。ということで__init()__.py
の中身を書いていきましょう。
**__init__.py
中身を書いてモジュール名の記入をカットした場合**
from fortune_package.lottery_module import *
from fortune_package.horoscope_module import *
__init__.py
の中身で、fortune_package
パッケージからlottery_module
モジュールとhoroscope_module
モジュールのそれぞれ全ての関数を*
でimport
します。
そうすると、このようにモジュール名をカットして実行することが出来ます。
import fortune_package as fp
#くじ引きがしたい場合
fp.lottery()
#星座占いがしたい場合
fp.horoscope()
#実行結果
"""
大吉
"""
"""
第1位はいて座のあなた!
第2位はてんびん座のあなた!
第3位は牡羊座のあなた!
第4位はみずがめ座のあなた!
第5位はしし座のあなた!
第6位はかに座のあなた!
第7位はやぎ座のあなた!
第8位はさそり座のあなた!
第9位はおうし座のあなた!
第10位はうお座のあなた!
第11位はふたご座のあなた!
第12位はおとめ座のあなた!
"""
無事カットできましたが、エンジニアとしてはやはり仕組みが知りたくなります。
仕組み
パッケージをimport
した際に、初期化処理として__init__.py
の中身のコードが裏で処理されるために表で書かなくて済むという仕組みです。
上記の例では、初期化処理で二つのモジュールの全ての関数をあらかじめimport
していたため、パッケージをimport
した時点で二つのモジュールを使うことが織り込み済みとなり、関数を使う際にモジュール名を書かなくてもパスを見失わず理解してくれたわけです。
快適なホテル体験のための優秀なホテルスタッフを育てる教育マニュアルを作る様に、快適にパッケージを使うための便利な初期化処理を司る__init__.py
を作るのです。
普段自分がよく使うパッケージの__init__.py
を覗いてみてください。たくさんの初期化処理によって使いやすくなる様に工夫がなされてます。作り手のホスピタリティを強く感じられます。
仕組みがわかれば応用が可能になります。
例えば、__init__.py
の中に関数を書くと、そのパッケージをimport
した際にモジュール名無しで使うことが出来ます。
__init__.py
についての詳しい情報は参考文献【3】と【4】からどうぞ。
fortune/
├───── fortune_package/
├───── __init__.py
├───── lottery_module.py
├───── horoscope_module.py
ここまでくるとファイル構成はこんな感じ。残るはsetup.pyのみ!ラストスパート!
【6】パッケージディレクトリにsetup.py
を用意し、pip
でのinstall
を可能にする。
setup.py
には、パッケージをpip
でinstall
する際に必要なsetuptools
に関する設定をします。
setup.py
は、パッケージの取扱説明書の様なものでpip
を使ってインストールする際にはこのsetup.py
の記述に従ってインストールされます。そのため、パッケージを正しく使えるようにするためのたくさんのオプションがあり、それらオプションを使いこなしてsetup.py
を設定してく必要があります。
ただし、今回は配布無しで自分が使う自作パッケージについての解説であるため、最低限必要な記述3つだけでsetup.py
の設定を済ませます。
配布する際には、インストールする方がどんな環境であっても正しくパッケージが利用できるようにする必要がありますので、setup.py
に関する詳しい解説は今後投稿されるであろう**Pythonパッケージの作り方(配布有り編)**でします。お待ちください。待ちきれない方は、参考文献【1】からどうぞ。
それでは、実際に設定していきましょう。
今回setup.py
に記述するのは、name
とversion
とpackages
の3つです。
書きあがったもがこちらです。
from setuptools import setup, find_packages
setup(
name="fortune_package",
version="1.0",
packages=find_packages()
)
まず、setup.py
で必要な関数であるsetup
をimport
します。
インストールする際に必要な情報は全てこのsetup
関数の中に記述していきます。
まずはname
ですが、これは単純にパッケージの名前を入力してください。
次にversion
ですが、これはパッケージのバージョンを入力してください。
最後にpackages
ですが、ここではfind_package
関数を使います。find_package()
は、パッケージをインストールする際に引数に指定した名前のディレクトリをプロジェクトディレクトリの中から探してパッケージとして扱います。引数が無い場合は、pip
でインストールする際のディレクトリ(プロジェクトディレクトリ)直下のパッケージディレクトリを自動的にパッケージとして扱います。
今回の場合、fortune
プロジェクトディレクトリでインストールを行えば、直下のfortune_package
パッケージディレクトリを自動的にパッケージとして扱ってくれます。
fortune/
├───── setup.py
├───── fortune_package/
├───── __init__.py
├───── lottery_module.py
├───── horoscope_module.py
これで、ファイル構成の全てを設定し終えることが出来ました。
最後は実際にインストールしてみましょう。
【7】完成!自分の実行環境にインストールしてみよう。
自作パッケージを自分のPCの実行環境にインストールして正しく利用できることを確認していきます。
まず、CMD、PowerShell、tarminalなどを立ち上げて、パスをプロジェクトディレクトリに移動してください。
C: Users\ユーザ名\Desktop\python files\fortune>
次に、pip install .
と入力してください。
C: Users\ユーザ名\Desktop\python files\fortune>pip install .
.
は現在のディレクトリの場所を指すので、fortune
プロジェクトディレクトリのsetup.py
の内容に従ってfortune_package
がパッケージとしてインストールされます。これで、以下の表示がされれば無事インストール完了です。
Successfully built fortune-package
Installing collected packages: fortune-package
Successfully installed fortune-package-1.0
インストールが完了したらPython
を起動して、パッケージをimport
して関数を実行してみて下さい。どのディレクトリでPython
を起動してもしっかりと利用できることでしょう。と、ここで最終チェックをします。
windows、anaconda、base(root)の実行環境でインストールした場合
C: Users\ユーザ名\anaconda3\Lib\site-packages
このパスを辿ってsite-packages
の中身を見て、パッケージディレクトリとパッケージ名-バージョン.dist-info
というディレクトリの二つがあることを確認してください。これで、他のサードパーティ製パッケージと同じく自作パッケージが使えることが確認できました。
windows、anaconda、任意の仮想環境の実行環境でインストールした場合
C: Users\ユーザ名\anaconda3\envs\仮想環境名\Lib\site-packages
このパスを辿ってsite-packages
の中身を見て、パッケージディレクトリとパッケージ名-バージョン.dist-info
というディレクトリの二つがあることを確認してください。これで、他のサードパーティ製パッケージと同じく自作パッケージが使えることが確認できました。
晴れて自作パッケージの完成です!お疲れさまでした。:thumbsup: