sys.path のハッキングにうんざりしていませんか?
利用可能なハックはたくさんありますがsys.path.append
、手元の問題を解決する別の方法を見つけました。
概要
- コードを 1 つのフォルダーにラップします (例:
packaged_stuff
)
- setuptools.setup()
setup.py
を使用するスクリプトを作成します。(以下の最小限を参照)setup.py
- 編集可能な状態でパッケージをピップインストールします
pip install -e <myproject_folder>
- を使用してインポート
from packaged_stuff.modulename import function_name
設定
開始点は、提供されたファイル構造であり、 というフォルダーにラップされていますmyproject
。
.
└── myproject
├── api
│ ├── api_key.py
│ ├── api.py
│ └── __init__.py
├── examples
│ ├── example_one.py
│ ├── example_two.py
│ └── __init__.py
├── LICENCE.md
├── README.md
└── tests
├── __init__.py
└── test_one.py
ルート フォルダーと呼びます。.
この例では、 にありますC:\tmp\test_imports\
。
api.py
テストケースとして、次の ./api/api.py を使用してみましょう
def function_from_api():
return 'I am the return value from api.api!'
test_one.py
from api.api import function_from_api
def test_function():
print(function_from_api())
if __name__ == '__main__':
test_function()
test_one を実行してみてください:
PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
Traceback (most recent call last):
File ".\myproject\tests\test_one.py", line 1, in <module>
from api.api import function_from_api
ModuleNotFoundError: No module named 'api'
また、相対インポートを試みてもうまくいきません:
を使用from ..api.api import function_from_api
すると、
PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
Traceback (most recent call last):
File ".\tests\test_one.py", line 1, in <module>
from ..api.api import function_from_api
ValueError: attempted relative import beyond top-level package
手順
- setup.py ファイルをルート レベル ディレクトリに作成します。
の内容は次のsetup.py
とおりです*
from setuptools import setup, find_packages
setup(name='myproject', version='1.0', packages=find_packages())
- 仮想環境を使用する
仮想環境に精通している場合は、仮想環境をアクティブにして、次の手順に進みます。仮想環境の使用は絶対に必要というわけではありませんが、長期的には非常に役立ちます (複数のプロジェクトが進行中の場合..)。最も基本的な手順は次のとおりです (ルート フォルダーで実行)。
- 仮想環境を作成する
- 仮想環境を有効にする
source ./venv/bin/activate
(Linux、macOS) または./venv/Scripts/activate
(Win)
これについて詳しく知るには、「python virtual env tutorial」などをグーグルで検索してください。おそらく、作成、アクティブ化、および非アクティブ化以外のコマンドは必要ありません。
仮想環境を作成してアクティブ化すると、コンソールに仮想環境の名前が括弧内に表示されます。
PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>
フォルダ ツリーは次のようになります**
.
├── myproject
│ ├── api
│ │ ├── api_key.py
│ │ ├── api.py
│ │ └── __init__.py
│ ├── examples
│ │ ├── example_one.py
│ │ ├── example_two.py
│ │ └── __init__.py
│ ├── LICENCE.md
│ ├── README.md
│ └── tests
│ ├── __init__.py
│ └── test_one.py
├── setup.py
└── venv
├── Include
├── Lib
├── pyvenv.cfg
└── Scripts [87 entries exceeds filelimit, not opening dir]
- プロジェクトを編集可能な状態で pip install
myproject
を使用して最上位パッケージをインストールしますpip
。トリックは-e
、インストールを行うときにフラグを使用することです。このようにして、編集可能な状態でインストールされ、.py ファイルに対して行われたすべての編集が、インストールされたパッケージに自動的に含まれます。
ルート ディレクトリで、次を実行します。
pip install -e .
(ドットに注意してください。「現在のディレクトリ」を表します)
を使用してインストールされていることも確認できます。pip freeze
(venv) PS C:\tmp\test_imports> pip install -e .
Obtaining file:///C:/tmp/test_imports
Installing collected packages: myproject
Running setup.py develop for myproject
Successfully installed myproject
(venv) PS C:\tmp\test_imports> pip freeze
myproject==1.0
myproject.
インポートに追加
myproject.
他の方法では機能しないインポートにのみ追加する必要があることに注意してください。setup.py
&なしで機能したインポートは、pip install
引き続き正常に機能します。以下の例を参照してください。
ソリューションをテストする
api.py
それでは、上で定義したものと下で定義したものを使用してソリューションをテストしましょうtest_one.py
。
test_one.py
from myproject.api.api import function_from_api
def test_function():
print(function_from_api())
if __name__ == '__main__':
test_function()
テストの実行
(venv) PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
I am the return value from api.api!
*より詳細な setup.py の例については、 setuptools のドキュメントを参照してください。
** 実際には、仮想環境をハードディスクのどこにでも置くことができます。