1. ホーム
  2. パイソン

[解決済み】兄弟パッケージのインポート

2022-03-28 03:49:44

質問

兄弟インポートについての質問を読んでみましたが、さらに パッケージ・ドキュメント しかし、まだ答えは見つかっていません。

以下のような構成で。

├── 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

のスクリプトはどのようにすればよいのでしょうか? examplestests ディレクトリからインポートします。 api モジュールで、コマンドラインから実行されるのですか?

また、醜い sys.path.insert のハックをすべてのファイルに適用しています。確かに これはPythonでできるんですよね?

どのように解決するのか?

7年後

以下の答えを書いたので、修正 sys.path は、プライベートスクリプトのためにうまく機能する迅速で汚いトリックであることに変わりはありませんが、いくつかの改良がなされました。

  • インストール を使えば、(仮想環境であろうとなかろうと)欲しいものが手に入りますが、setuptoolsを直接使うよりも、pipを使ってやることをお勧めします(そして setup.cfg メタデータを保存するため)
  • を使用して -m フラグ で、パッケージとして実行することもできます(ただし、作業ディレクトリをインストール可能なパッケージに変換したい場合は、少し厄介なことになります)。
  • テストのために、具体的には pytest はこのような状況でもapiパッケージを見つけることができ、また sys.path ハックする

ですから、あなたが何をしたいのかに本当によります。あなたの場合、いずれはきちんとしたパッケージを作ることが目的のようなので、インストールは pip -e は、まだ完璧ではないにせよ、おそらく最良の策だと思います。

古い回答

すでに他の場所で述べたように、兄弟モジュールや親パッケージからのインポートを許可するには、醜いハックをしなければならないというひどい現実があります。 __main__ モジュールです。この問題の詳細は PEP 366 . PEP 3122 は、より合理的な方法でインポートを処理しようとしましたが、Guidoはそれを拒否しています。

<ブロッククオート

唯一のユースケースは、たまたま実行されたスクリプトが モジュール・ディレクトリの中に住んでいること。 アンチパターン

( ここで )

とはいえ、このパターンを常用するのは

# Ugly hack to allow absolute import from the root folder
# whatever its name is. Please forgive the heresy.
if __name__ == "__main__" and __package__ is None:
    from sys import path
    from os.path import dirname as dir

    path.append(dir(path[0]))
    __package__ = "examples"

import api

ここで path[0] は実行中のスクリプトの親フォルダで dir(path[0]) トップレベルフォルダ

しかし、この方法では相対的なインポートを使用することはまだできませんが、トップレベルからの絶対的なインポートを可能にします(あなたの例で言えば api の親フォルダ)。