兄弟パッケージのインポート 質問する

兄弟パッケージのインポート 質問する

私は兄弟インポートに関する質問や、パッケージドキュメント、しかし、私はまだ答えを見つけていません。

次の構造になります。

├── 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 を使用しています。他の選択肢もあります。

** 実際には、仮想環境をハードディスク上のどこにでも配置できます。

おすすめ記事