7

「project」というフォルダーに Python コードがあるため、コード ファイルは project/*.py にあります。その中にサブモジュールが必要です。

project/code.py # where code lives
project/mymodule1  # where more code lives
project/mymodule2

各モジュールディレクトリには、独自のinit .py ファイルがあります。

project/mymodule1/__init__.py

mymodule1 (project/mymodule1/test.py) 内にファイル「test.py」があり、「コード」から何かを参照したいとします。たとえば、関数「myfunc」をインポートします。

== project/mymodule1/test.py ==
from code import myfunc

問題は、ユーザーが「project/」ディレクトリを PYTHONPATH に配置しない限り、「コード」が見つからないことです。これを回避し、ある種の「相対パス」を使用して myfunc をインポートする方法はありますか?

from ../code import myfunc

基本的に、スクリプト内からプログラムで変更できない限り、コードのユーザーに PYTHONPATH の変更を強制したくありません。私はそれが箱から出して動作することを望みます。

これはどのように行うことができますか?どちらの解決策も良いです: プログラムで PYTHONPATH を変更するか、より理想的には、ある種の相対インポートを使用して「コード」を参照します。それは「myfunc」に関連しています。

編集:誰かがパッケージ内インポートの適切な例を示してもらえますか? 「mymodule1」からやってみました:

from .. import foo

「foo」はcode.pyにありますが、機能しません。mymodule1 に init .py があるので、次のようにします

project/code.py
project/mymodule1/__init__.py
project/mymodule1/module1_code.py

ここで、module1_code.py は、「code.py」で定義された関数である foo をインポートしようとします。

編集:私がまだ抱えている主な混乱は、プロジェクト/サブ1/テスト階層を示す私のメッセージに応答して与えられた例を採用した後でも、サブ1に「cd」して「python test.py」を実行してそれを実行できないことです。仕事。ユーザーは「project」を含むディレクトリにいて、「import project.sub1.test」を実行する必要があります。ユーザーがどのディレクトリにいるかに関係なく、これが機能することを望みます。この場合、ユーザーは project/sub1/ にあるファイル「test.py」を実行する必要があります。したがって、テストケースは次のとおりです。

$ cd project/sub1
$ python test.py

エラーが発生します:

ValueError: Attempted relative import in non-package

これはどのように修正できますか?

ありがとう。

4

2 に答える 2

4

これは Python 2.5 以降で可能です。Intra-Package Referencesのドキュメントを参照してください。

注意すべき点がいくつかあります。

たとえば、distutils や setuptools を使用して、ユーザーがパッケージをどこかにインストールすることを意図している場合projectは、すでに検索パスにある可能性が高く、相対インポートを次のように変更できますfrom project.code import ...

ユーザーがあなたのパッケージを非標準のディレクトリ (例えば、ホームディレクトリや にない別の場所など) にインストールしている場合、私の意見では、プログラムで変更するよりもsys.path、変更するようにユーザーに指示した方が混乱が少なくなります。PYTHONPATH変更sys.path

ユーザーがコードをインストールすることをまったく意図していない場合-たとえば、ユーザーは単にソースを展開し、 の親ディレクトリに cd してproject、スクリプトを実行します-その後、パッケージ内参照と相対インポートはおそらくうまくいくでしょう。

編集:リクエストごとに、例を次に示します。

パッケージのレイアウトが次のようになっているとします。

project/
    __init__.py (empty)
    code.py
    sub1/
        __init__.py (empty)
        test.py

現在、の内容は次のproject/code.pyとおりです。

# code.py (module that resides in main "project" package)

def foo():
    print "this is code.foo"

そして、の内容は次のproject/sub1/test.pyとおりです。

# test.py (module that resides in "sub1" subpackage of main "project" package)

from ..code import foo
foo()

そのため、相対パスからtest.py名前をインポートします。これは、パッケージ内参照を使用して、実行元のパッケージの(その部分)内のモジュールに戻ります。foo..codecode.py..sub1.test

これをテストするには:

shell$ (cd to directory where "project" package is located)
shell$ python
Python 2.6.1 (r261:67515, Aug  2 2010, 20:10:18) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import project.sub1.test
this is code.foo

構文の二重ドットfrom .. import Xは親パッケージに移動するだけですが、そのパッケージ内でモジュールを指定できることに注意してください。

つまり、from .. import Xこの場合は と同等from project import Xであり、したがってX内のモジュールprojectまたは 内のクラス/関数/名前のいずれかでなければなりませんproject/__init__.py

したがって、from ..code import Xと同等from project.code import Xです。

于 2011-12-06T18:11:57.837 に答える
1

これを回避する最善の方法は、すべてのコードをsrcフォルダーに保持するか、プロジェクトで名前を付けて、そこにmyproject保持する__init__.pyことです。これにより、これを実行できます。

from myproject import code

したがって、フォルダ構造は次のようになります。

project
    main.py
    myproject
        __init__.py
        code.py
        module1
        module2

main.pyまたは、名前に付けた名前にコードを多く含まないようにする必要があります。必要なモジュールを取得しmyprojectて実行する必要があります。

from myproject import myapp
myapp.run()

Pythonプロジェクトを配置する方法についての良い記事を参照してください。

于 2011-12-06T18:12:55.010 に答える