2016-06-28 15 views
1

私は過去1時間をGoogleとSOを使って過ごしました。まだ別のものを追加して申し訳ありませんが、答えはどれも私のためにはうまくいきません。兄弟ディレクトリからPythonクラスをインポートする

/VM/repo/projectで私のディレクトリ構造は次のとおりです。

__init__.py 

scripts/ 
     getSomething.py 
     __init__.py 

classes/ 
     project.py 
     db.py 
     __init__.py 

====================

getSomething.py

from ..classes import project 
from ..classes import db 

==================

project.py

class PROJECT: 
def __init__(self): 
    stuff 

====================

db.py

class DB: 
def __init__(self): 
    stuff 

===========

私はエラーに取得

python getSomething.py

を実行しよう=========

Traceback (most recent call last):

File "scripts/getSomething.py", line 4, in < module >

from ..classes import project

ValueError: Attempted relative import in non-package

私はここで何が欠けていますか?

答えて

4

エラーで述べたように、getSomethingをメインモジュールとして実行しています。しかし、あなたがパッケージに入っていないときは、パッケージ相対インポートを行うことはできません。メインモジュールは決してパッケージに入っていません。あなたは...パッケージの一部としてgetSomethingをインポートしていたのであれば、:

# /VM/repo/main.py 
from project.scripts import getSomething 

を次に、インポートエラーを持っていないでしょう。


おそらく、Pythonモジュールとパッケージについて簡単に議論することは役に立ちます。一般に、pythonのソースコードを含み、拡張子が.pyのファイルがモジュールです。通常、モジュールの名前はファイル名(拡張子)ですが、直接実行すると、そのモジュールの名前は'__main__'になります。これまでのところ、これはすべてよく知られており、文書化されています。モジュールをインポートするには、import moduleまたはimport package.moduleなどとします。この最後のインポートステートメントは、他のもの(パッケージ)を参照しています。

パッケージはインポートできるディレクトリです。多くのディレクトリをインポートすることはできません(たとえば、Pythonソースファイルがない場合もあります)。したがって、このあいまいさを解決するには、ディレクトリに__init__.pyファイルがあるという要件もあります。ファイルシステム上のディレクトリをインポートすると、pythonは実際に__init__.pyモジュールをインポートし、__init__.py(存在する場合)のものから関連パッケージを作成します。

これをまとめると、なぜ__init__.pyというディレクトリ内のファイルを実行するだけでは、モジュールがパッケージの一部であるとみなすには十分ではありません。まず、モジュールの名前は__main__であり、package.filename_sans_extensionではありません。第2に、パッケージの作成は、ファイルシステムの構造だけでなく、ディレクトリ(したがって__init__.pyが実際にインポートされたかどうか)にも依存します。

あなたは「なぜこのようにデザインしたのですか?」と尋ねているかもしれません。確かに、私は機会に同じ質問をしてきました。その理由は、言語デザイナーがパッケージの特定の保証を必要としているからです。パッケージは、特定の目的のために一緒に働くように設計されたものの単位でなければなりません。それはいくつかの無防備な__init__.pyファイルによって、必要な他のモジュールを見つけるためにファイルシステムを回る能力を得るスクリプトのサイロであってはなりません。何かがメインモジュールとして実行されるように設計されている場合は、パッケージの一部ではないはずです。むしろ、パッケージをインポートしてそれに依存する別個のモジュールでなければなりません。

+0

私は、各ディレクトリに '__init __。py'を追加することは、基本的にそれらのディレクトリをパッケージとして定義するという印象を受けましたか?私はパッケージの基本的な誤解をここに持っているかもしれません。なぜ、メインモジュールはパッケージ化されていないのですか? 第二に、私の目標はcronでスクリプトを実行することです。クラスをスクリプトに直接インポートする方法はありませんか?別のファイル 'main.py'をもう一つ作成することは、不必要に私に巻き込まれるようです。 – ShaneOH

+1

@ShaneOH - 曖昧さを解決するために私の答えを編集しようとしました。 – mgilson

+0

元の回答と編集は非常に役に立ちます。だから私は最後の質問が1つあります。このディレクトリ構造を維持し、スクリプトをメインモジュールとして直接実行したいのですが?だから、彼らはパッケージの一部である必要はありません。/classesモジュールを兄弟フォルダのメインモジュールにインポートするにはどうすればよいですか?そして、/ scriptsと/ projectから '__init __。py'を削除しますか? – ShaneOH

関連する問題