Pythonで上位ディレクトリにある自作パッケージをインポートして使いたいが、相対パスによるインポートや、スクリプト内でsys.pathを変更したくない場合の対処方法がなかなか見つからなかったので、書き置きします。
結論的には setup.py
を作成し pip install -e .
というコマンドを使います。
構成
ディレクトリ構成例:
project
+ mypackage
| + __init__.py
| + module_a.py
+ myprogram1
| + executor
| + executor.py
| + tests
| + ...
| + env
| + requirement.txt
+ myprogram2
| ...
+ setup.py
executor.py
からみて上位フォルダに有る mypackage
という自作パッケージをインポートして使いたい。
myprogram1
, myprogram2
... は独立していて、それぞれ別の仮想環境(virtualenv)、パッケージ管理(pip), **単体テスト(testsフォルダ)**で構成が可能。
私の場合、Serverlessフレームワークで構成された独立してデプロイ可能なAWS Lambdaのサービス用のディレクトリが複数あり、また共通処理としてLambdaLayerを上位のフォルダに配置していたため、ローカルでLambdaの関数からLambdaLayerが正しくインポートできずにいた。
詳細
自作パッケージ作成
module_a.py の中身
def hello():
print('Hello World')
setup.py の 配置
以下のような setup.py
をルートディレクトリに置く。
from setuptools import setup, find_packages
setup(name='myproject', version='1.0', packages=find_packages())
find_packages() は自動的に __init__.py
が存在するパッケージを探索してくれる。 ルートディレクトリからは、mypackageが見つかる。
それ以外のsetup()の中身は適当です。
自作パッケージをpipインストール
あとは各ディレクトリで以下のコマンドを実行することで、自作パッケージをインストールする。
cd myprogram1
pip install -U -e ../
-U または --upgrade はパッケージを最新状態に更新する。
-e または --editable は自作パッケージを編集し保存する際、自動的に変更を認識してくれる為、自作パッケージの再インストール(pip install)が不要になる。
自作パッケージのインポート
executor.py
from mypackage import module_a # 自作パッケージ
module_a.hello() # 呼び出し
実行
> python executor/executor.py
Hello World
参考
修正履歴
- 20/6/28 一部修正と、説明がシンプルになるように削りました。