Pythonのパッケージ構成とimport文

パッケージについて

PyPIとかへの登録とかはおいておいて,自作パッケージをimportしたり,他のプログラムから使おうとするときの方法を整理しておく。下記に従えば,最悪,mypackage以下を開発中のパッケージにコピーすれば,そのまま使える。

ディレクトリ構成

  • git管理ディレクトリMyPackageに以下の構成にてディレクトリを作成する。
  • パッケージ名はmypackage(全部小文字)とし,すべてMyPackage/mypackage以下に関連ソースコード,データを配置する。基本的にはこのディレクトリがパッケージのトップディレクトリであると考える。
  • パッケージの中で静的データを使う場合(例えばゲームのマップファイルなど)は,mypackage以下に置く。間違ってMyPackage以下に置かない。繰り返すが,トップディレクトリはmypackage。
    • サンプル実行コードてテストコード,ドキュメントはMyPackage以下に配置する。これらはpackageのインストール自体では入らない。
MyPackage
    - mypakcage  # ソースコードをインストールするディレクトリ
        - hoge.py
        - foo
            - bar.py
        - data
            - data1.dat
            - data2.dat
    - sample
        - sample.py
    - doc
    - test

各ファイルの注意

パッケージ内のimport文

  • 基本的に相対インポートは書かない。絶対インポートを書く。(相対インポートよりもわかりやすいと思う。ディレクトリ構成がコロコロ変わると厄介だけど)
  • 例えば,bar.pyをhoge.pyがインポートする場合は下記のように書く。
# hoge.py
from mypackage.foo import bar  # Good
from foo import bar # <= Bad

sample/test内のimport文

  • sample/sample.pyは兄弟ディレクトリのmypakcage以下のファイルをそのままではインポートできない。よって,pathに追加する。
  • その際にはfileがそのファイルのパスを表すこと活用して,親ディレクトリをパスに追加する。os.path.dirnameを2回適用することで,親ディレクトリの絶対パスを求めている。".."を使うと実行ディレクトリに依存するのでその記述は避ける(Pythonは実行ディレクトリをカレントディレクトリとする)
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

静的データのパス

  • マップデータやイメージなどの静的データをロードする場合も同様に,fileがそのファイルのパスを表すことを利用して,パッケージが配置される絶対パスからパスを指定する。
# hoge.pyからdata/data1.datをロードする場合
import os
dir_path = os.path.dirname(os.path.abspath(__file__))
data = dir_path + '/data/data1.dat'