Python で既知の親パッケージがない相対インポートの試みを解決する

Olorunfemi Akinlua 2023年6月21日
Python で既知の親パッケージがない相対インポートの試みを解決する

Python での相対インポートは、特に 1つのディレクトリ内で複数のモジュールを処理する場合に注意が必要です。 Python コードベースの設計方法によっては、ImportError が発生する場合があります。

ただし、インポート システムを十分に理解していれば、ImportError: 既知の親パッケージがない相対インポートを試行しましたなどのエラーを防ぐのに十分です。 エラー メッセージにより、問題の原因を簡単にトラブルシューティングできます。

この場合、親パッケージが存在しないことが原因です。 この記事では、ImportError 問題を解決する方法を紹介し、説明します。

サブモジュール を使用して、Python で ImportError: 既知の親パッケージがない相対インポートを試みました を解決する

以下のコードのように、.module_name 式を使用すると、エラー ImportError: attempts relative import with no known parent package が発生します。

import .module_name

新しいディレクトリ内に 3つのファイルを作成して、問題を再現してみましょう。 以下の構造を使用してテストできます。

IError ディレクトリにはすべての Python コードが格納され、myPackage ディレクトリにはすべてのパッケージ ファイルが格納されます。 次に、[main.py]myPackage.py にアクセスします。

IError/
    myPackage/
        __init__.py
        myNewPackage.py
    main.py

エラー メッセージを再現するには、__init__.py ファイルのみが必要です。 __init__.py ファイルは、ディレクトリに Python モジュール コード (この場合は myNewPackage.py) が含まれていることを Python インタープリターに知らせます。

エラーを再現する前に、3つの Python ファイルすべてに含まれるコードを書きましょう。

myNewPackage.py ファイルには、以下のコード スニペットが含まれています。

def createSingleDict(name, value):
    return {"name": name, "value": value}

__init__.py ファイル:

from .myNewPackage import createSingleDict

myPackage モジュールを使用する main.py ファイル:

import myPackage as pkg

User = pkg.createSingleDict("Jacob", 25)

print(User)

myNewPackage.py には、2つの引数を取り、渡された引数で辞書を返す単一の関数が含まれています。 __init__.py は、import ステートメントとキーワード from および import を使用して、myNewPackage.py__init__.py ファイルにインポートします。

main.pymyPackage.myNewPackage 式を使用せずに myPackage をインポートします。 これらはすべてサブモジュールのおかげで可能です。

__init__.py ファイルとその中のステートメントは、myNewPackage ファイル (属性) が親 (myPackage) 名前空間にバインドされるサブモジュール メカニズムをロードします。

__init__.py ファイル内のステートメントの重要な部分は、モジュール名の前の ドット です。 これにより、親のモジュールに配置されたものへのバインドが可能になります。

エラー メッセージの既知の親パッケージがありませんという部分を思い出してください。 これが、エラーが発生している理由です。

__init__.py ファイルだけを実行してみましょう。 実行の出力は以下のとおりです。

Traceback (most recent call last):
  File "c:\Users\akinl\Documents\IError\myPackage\__init__.py", line 1, in <module>
    from .myNewPackage import createSingleDict
ImportError: attempted relative import with no known parent package

親名前空間 myPackage のコンテキストなしで __init__.py ファイルを実行しているため、このエラーが発生します。 ただし、main.pyimport ステートメント import myPackage as pkg で実行すると、エラーは発生しません。

出力は以下のとおりです。

{'name': 'Jacob', 'value': 25}

したがって、. は使用しないでください。 __init__.py または親名前空間のバインディングまたはコンテキスト内でない限り、module_name の前に演算子を使用して、ImportError: 既知の親パッケージが存在しない相対インポートを試みました を防ぎます。

. を削除すると、何が起こっているのかをよりよく理解できます。 __init__.pyimport ステートメント内で演算子を使用すると、ファイルの実行中にエラーが発生しなくなります。

from myNewPackage import createSingleDict

ただし、main.py ファイルを実行すると、myNewPackage モジュールを親モジュール myPackage にバインドしていないため、以下のエラーが発生します。

Traceback (most recent call last):
  File "c:\Users\akinl\Documents\IError\tempCodeRunnerFile.py", line 1, in <module>
    import myPackage as pkg
  File "c:\Users\akinl\Documents\IError\myPackage\__init__.py", line 1, in <module>
    from myNewPackage import createSingleDict
ModuleNotFoundError: No module named 'myNewPackage'

コードを実行するには、. を使用する必要があります。 main.pyimport ステートメント内の演算子と __init__.py ファイルを削除 (削除) します。

import myPackage.myNewPackage as pkg

User = pkg.createSingleDict("Jacob", 25)

print(User)

ただし、これは面倒なので、. を使用してサブモジュールを親モジュールにバインドする方が理にかなっています。 __init__.py 内の演算子ですが、常に親コンテキスト内で実行していることを確認してください。

サブモジュールが 2つある場合も、同じように機能します。 新しいサブモジュール otherPackage.py には、次のコードが含まれる場合があります。

def printName(name):
    print("The user's name is " + name)

__init__.py ファイルを更新して、新しいサブモジュールを親名前空間にバインドします。

from .myNewPackage import createSingleDict
from .otherPackage import printName

また、main.py 内では、エイリアス pkg を使用して、他のサブモジュール内の関数にアクセスする必要があります。 それが、親の名前空間へのバインドの利点であり、インポートの容易さです。

import myPackage as pkg

User = pkg.createSingleDict("Jacob", 25)

print(User)
pkg.printName("Jacob")

コードの出力:

{'name': 'Jacob', 'value': 25}
The user's name is Jacob

これらすべてを使用すると、Python コードベース内の ImportError: 既知の親パッケージがない相対インポートを試行しました を防止または解決するために必要なすべての情報が得られます。

Olorunfemi Akinlua avatar Olorunfemi Akinlua avatar

Olorunfemi is a lover of technology and computers. In addition, I write technology and coding content for developers and hobbyists. When not working, I learn to design, among other things.

LinkedIn

関連記事 - Python Error