蛇使いな彼女BLOG
【第128回】.pyファイルのパッケージ化について
2025.05.02

今日はタイトルの通り、Pythonプログラムが入ったフォルダのパッケージ化について説明していきます。
最近仕事の都合でこのような処理が必要になった事から、こちらに手順をまとめておこうと思いました。
用途はコマンドラインからプログラムの実行する場合や、譲渡を目的にしています。
ですので、ここで言うパッケージとは、アプリケーション的なグラフィカル操作は含みません。
【ディレクトリツリー】
C:.
│ mein.py
│ mein.pyproj
│
└─package
│ A.py
│ B.py
│ __init__.py
│
└─__pycache__
A.cpython-36.pyc
B.cpython-36.pyc
__init__.cpython-36.pyc
今回扱う構造は上で示すとおり。
mein.pyからpackageフォルダ直下のA.pyとB.pyをモジュールとして機能させるという仕様です。
サンプルコードは、ゲームでよくある確率ガチャを実装してみました😳
結果はレアリティと16種類のタイプの組み合わせで排出されます。
~/package/
from . import A from . import B
import numpy as np class Content(): def __init__(self): self.distribution=["N", "HN", "R", "SR","UR"] self.probability=[0.5,0.3,0.14,0.05,0.01] self.elements=[ "Fire","Water","Grass","Bug","Steel","Poison","Normal","Electric", "Rock","Ground","Flying","Fighting","Evil","Psychic","Dragon","Fairy" ] @property def prob(self): return self.probability @prob.setter def prob(self,prob): self.probability=prob def output_prob(self,size=1): Rarity=np.random.choice(self.distribution,size=size, p=self.probability) Type=np.random.choice(self.elements,size=size,) result=np.vstack((Rarity,Type)) return result.T
import numpy as np from . import A class Bonus(A.Content): def __init__(self): super().__init__() self.items={ 'up':[0.4,0.25,0.2,0.1,0.05], 'down':[0.5,0.275,0.2,0.02,0.005], 'none':[0.5,0.3,0.14,0.05,0.01], } def Get_item(self,): magnification=np.random.choice(['up','down','none'], p=[0.5,0.2,0.3]) self.probability=self.items[magnification] return magnification
main.py
from package import A from package import B # 通常確率で排出 print('Random character creation') Con=A.Content() print('Normal probability') Con.prob Con.output_prob(10) # ボーナス確率で排出 print('Probability bonus') Bon=B.Bonus() print('結果:',Bon.Get_item()) Bon.prob Bon.output_prob(10)
各Pythonスクリプトの役割については以下の通りで、
-
- A.py:親クラス。主なレアリティとタイプを記載
- B.py:子クラス。排出されるレアリティ確率を操作できる設定
- main.py:A.pyとB.pyを呼び出して実行するスクリプト
となっています。
排出確率は(アルファベットの解釈が多数あるようですが)今回は
"N"(ノーマル)50%
"HN"(ハイノーマル)30%
"R"(レア)14%
"SR"(スーパーレア)5%
"UR"(ウルトラレア)1%
これに対し16個のタイプが1/16の確率で組み合わさるものとしました。
main.pyを動かしてみると、
(コマンドラインの実行結果)
(base) PS C:\Users\…\mein\mein> python mein.py
Random character creation
Normal probability
Probability bonus
結果: up
(VisualStudio2022の実行結果)
...
>>> # 通常確率で排出
... print('Random character creation')
...
Random character creation
>>> Con=A.Content()
>>> print('Normal probability')
Normal probability
>>> Con.prob
[0.5, 0.3, 0.14, 0.05, 0.01]
>>> Con.output_prob(10)
array([['N', 'Rock'],
['R', 'Evil'],
['N', 'Fairy'],
['HN', 'Fighting'],
['HN', 'Steel'],
['N', 'Psychic'],
['SR', 'Ground'],
['SR', 'Bug'],
['HN', 'Fire'],
['N', 'Steel']], dtype='<U8')
>>> # ボーナス確率で排出
... print('Probability bonus')
...
Probability bonus
>>> Bon=B.Bonus()
>>> print('結果:',Bon.Get_item())
結果: up
>>> Bon.prob
[0.4, 0.25, 0.2, 0.1, 0.05]
>>> Bon.output_prob(10)
array([['N', 'Psychic'],
['HN', 'Fighting'],
['HN', 'Grass'],
['HN', 'Normal'],
['R', 'Bug'],
['N', 'Electric'],
['R', 'Water'],
['N', 'Fighting'],
['N', 'Bug'],
['N', 'Fire']], dtype='<U8')
>>>
こんな感じで結果が出力されます。
この時、package側のインポート文の記述が通常と異なっているので簡単に説明すると、
通常、Pythonでは「import numpy as np」のようなimport (ライブラリ名) または from (ライブラリ名) import (モジュール名)といった絶対インポートを推奨していますが、これはメインプログラムに限ってであって、
package内のモジュール間でインポートを行う場合、importの前に「.」をつけることで相対インポートを行っています。このときの「.」は”現在のディレクトリ”を表しています。
そして、パッケージ化には__init__.pyの追加が必要だといわれますが、実はなくても普通に動きます。
(base) PS C:\Users\…\mein_2\mein_2> python mein_2.py
Random character creation
Normal probability
Probability bonus
結果: down
(base) PS C:\Users\…\mein_2\mein_2> tree /f
...
C:.
│ mein_2.py
│ mein_2.pyproj
│
└─package
│ A.py
│ B.py
│
└─__pycache__
A.cpython-36.pyc
B.cpython-36.pyc
大きなプロジェクトだと__init__.pyがあったほうが都合がいい場合もありますが、この程度のプログラムなら全く問題ないようです。
それでも__init__.pyを置く場合は、中身が空だろうが例のようにインポート文を書こうが、ご自由に。ということらしいです。(へぇ~)
結論としては、モジュールA・B、main.pyの冒頭インポートの記述を明示すれば、そのまま別のパソコンへ譲渡可能なんですね!ハイテクだ。(※プロジェクトの起動にはPython環境が必要)
そんなこんなで今回の話は終わりです
次回に続く。