私は兄弟インポートに関する質問や、パッケージドキュメント、しかし、私はまだ答えを見つけていません。
次の構造になります。
├── LICENSE.md
├── README.md
├── api
│ ├── __init__.py
│ ├── api.py
│ └── api_key.py
├── examples
│ ├── __init__.py
│ ├── example_one.py
│ └── example_two.py
└── tests
│ ├── __init__.py
│ └── test_one.py
examples
およびディレクトリ内のスクリプトをモジュールtests
からインポートしapi
、コマンドラインから実行するにはどうすればよいですか?
また、すべてのファイルに対して醜いハックを避けたいのですがsys.path.insert
、これは Python で実行できるはずですよね?
ベストアンサー1
sys.path ハックにうんざりしていませんか?
利用できる -hackはたくさんありますsys.path.append
が、私は手元の問題を解決する別の方法を見つけました。
まとめ
- コードを1つのフォルダにまとめます(例
packaged_stuff
:) pyproject.toml
パッケージを説明するファイルを作成します(pyproject.toml
以下に最小限のものを示します)- pipで編集可能な状態でパッケージをインストールします
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!'
テスト
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
手順
1) ルートレベルのディレクトリにpyproject.tomlファイルを作成します。
(以前はsetup.pyファイルが使用されていました)
最小限の内容はpyproject.toml
次のようになります*
[project]
name = "myproject"
version = "0.1.0"
description = "My small project"
[build-system]
build-backend = "flit_core.buildapi"
requires = ["flit_core >=3.2,<4"]
2) 仮想環境を使用する
仮想環境に慣れている場合は、仮想環境をアクティブにして、次のステップに進んでください。仮想環境の使用は絶対に必要というわけではありませんが、長期的には(複数のプロジェクトが進行中の場合など)非常に役立ちます。最も基本的な手順は次のとおりです(ルート フォルダーで実行)。
- 仮想環境を作成する
python -m venv venv
- 仮想環境をアクティブにする
source ./venv/bin/activate
(Linux、macOS) または./venv/Scripts/activate
(Win)
これについてさらに詳しく知るには、「python virtual env tutorial」などと Google で検索してください。作成、アクティブ化、非アクティブ化以外のコマンドはおそらく必要ありません。
仮想環境を作成してアクティブ化すると、コンソールに仮想環境の名前が括弧内に表示されます。
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
├── pyproject.toml
└── venv
├── Include
├── Lib
├── pyvenv.cfg
└── Scripts [87 entries exceeds filelimit, not opening dir]
3) 編集可能な状態でプロジェクトをpipでインストールします
myproject
を使用してトップレベルのパッケージをインストールしますpip
。インストール時にフラグを使用するのがコツです-e
。この方法では編集可能な状態でインストールされ、.py ファイルに加えられたすべての編集はインストールされたパッケージに自動的に含まれます。pyproject.tomlと -e フラグを使用するには、pip >= 21.3 が必要です。
ルートディレクトリで、
pip install -e .
(ドットは「現在のディレクトリ」を表します)
次のようにインストールすることもできます。pip freeze
Obtaining file:///home/user/projects/myproject
Installing build dependencies ... done
Checking if build backend supports build_editable ... done
Getting requirements to build editable ... done
Preparing editable metadata (pyproject.toml) ... done
Building wheels for collected packages: myproj
Building editable for myproj (pyproject.toml) ... done
Created wheel for myproj: filename=myproj-0.1.0-py2.py3-none-any.whl size=903 sha256=f19858b080d4e770c2a172b9a73afcad5f33f4c43c86e8eb9bdacbe50a627064
Stored in directory: /tmp/pip-ephem-wheel-cache-qohzx1u0/wheels/55/5f/e4/507fdeb40cdef333e3e0a8c50c740a430b8ce84cbe17ae5875
Successfully built myproject
Installing collected packages: myproject
Successfully installed myproject-0.1.0
(venv) PS C:\tmp\test_imports> pip freeze
myproject==0.1.0
4)myproject.
インポートに追加する
myproject.
そうでなければ機能しないインポートにのみ追加する必要があることに注意してください。 pyproject.toml
&なしで機能したインポートはpip install
、引き続き正常に機能します。以下の例を参照してください。
ソリューションをテストする
api.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!
* ここではビルド バックエンドとして flit を使用しています。他の選択肢もあります。
** 実際には、仮想環境をハードディスク上のどこにでも配置できます。