蛇使いな彼女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環境が必要)
そんなこんなで今回の話は終わりです
次回に続く。

06-6657-5130
sales@hydrolab.co.jp