88

次のディレクトリ構造があるとします。

a\
    __init__.py
    b\
        __init__.py
        c\
            __init__.py
            c_file.py
        d\
            __init__.py
            d_file.py

aパッケージのに__init__.pycパッケージがインポートされます。しかし、c_file.pyインポートしa.b.dます。

をインポートしようとすると、b存在しないと言ってプログラムが失敗します。(そして、インポートの途中だったので、実際には存在しません。)c_file.pya.b.d

この問題はどのように解決できますか?

4

7 に答える 7

169

a/__init__.pyたとえば、次のように、インポートを延期できます。

def my_function():
    from a.b.c import Blah
    return Blah()

つまり、本当に必要になるまでインポートを延期します。ただし、指摘されたような循環依存関係は設計上の問題を示している可能性があるため、パッケージの定義/使用も詳しく調べます。

于 2009-10-12T19:27:53.570 に答える
66

a が c に依存し、c が a に依存している場合、それらは実際には同じ単位ではありませんか?

a と c を 2 つのパッケージに分割した理由を実際に調べる必要があります。別のパッケージに分割する必要があるコードがあるか (両方を新しいパッケージに依存させるが、互いに依存しないようにするため)、またはそれらをマージする必要があるためです。 1つのパッケージに。

于 2009-10-12T19:33:28.410 に答える
34

私はこれについて数回疑問に思いました (通常、お互いについて知る必要があるモデルを扱っている間)。簡単な解決策は、モジュール全体をインポートしてから、必要なものを参照することです。

だから代わりに

from models import Student

一つで、そして

from models import Classroom

他の場合は、単に行う

import models

models.Classroomそれらのいずれかで、必要なときに呼び出します。

于 2013-10-04T16:18:32.150 に答える
0

問題は、ディレクトリから実行する場合、デフォルトではサブディレクトリであるパッケージのみがインポート候補として表示されるため、abd をインポートできないことです。ただし、b は a のサブパッケージであるため、bd をインポートできます。

本当に abd をインポートしたい場合はc/__init__.py、システム パスを a の 1 つ上のディレクトリに変更し、インポートをa/__init__.pyimport abc に変更することでこれを実現できます。

次のa/__init__.pyようになります。

import sys
import os
# set sytem path to be directory above so that a can be a 
# package namespace
DIRECTORY_SCRIPT = os.path.dirname(os.path.realpath(__file__)) 
sys.path.insert(0,DIRECTORY_SCRIPT+"/..")
import a.b.c

モジュールを c でスクリプトとして実行する場合は、さらに問題が生じます。ここでは、パッケージ a と b は存在しません。c ディレクトリをハックし__int__.pyて sys.path を最上位ディレクトリにポイントし、c__init__内の任意のモジュールをインポートして、絶対パスを使用して abd をインポートできるようにすることができます__init__.py。私のユースケースでうまくいきました。

于 2015-08-30T23:33:12.787 に答える
-4

別の解決策は、d_fileにプロキシを使用することです。

たとえば、blahクラスをc_fileと共有したいとします。したがって、d_fileには次のものが含まれます。

class blah:
    def __init__(self):
        print("blah")

c_file.pyに入力する内容は次のとおりです。

# do not import the d_file ! 
# instead, use a place holder for the proxy of d_file
# it will be set by a's __init__.py after imports are done
d_file = None 

def c_blah(): # a function that calls d_file's blah
    d_file.blah()

そして、のinit .py:

from b.c import c_file
from b.d import d_file

class Proxy(object): # module proxy
    pass
d_file_proxy = Proxy()
# now you need to explicitly list the class(es) exposed by d_file
d_file_proxy.blah = d_file.blah 
# finally, share the proxy with c_file
c_file.d_file = d_file_proxy

# c_file is now able to call d_file.blah
c_file.c_blah() 
于 2012-07-17T11:33:26.590 に答える