576

このディレクトリ構造を想像してみてください。

app/
   __init__.py
   sub1/
      __init__.py
      mod1.py
   sub2/
      __init__.py
      mod2.py

コーディングmod1しているので、から何かをインポートする必要がありmod2ます。どうすればいいですか?

試しfrom ..sub2 import mod2ましたが、「パッケージ以外で相対インポートを試みました」というメッセージが表示されます。

sys.pathグーグルで検索しましたが、「操作」ハックしか見つかりませんでした。きれいな方法はありませんか?


編集:すべての私__init__.pyのは現在空です

Edit2:sub2には、サブパッケージ(、、など)間で共有されるクラスが含まれているため、これを実行しようとしていsub1ますsubX

Edit3:私が探している動作は、PEP 366で説明されているものと同じです(John Bに感謝)

4

18 に答える 18

368

誰もが、質問に答えるだけでなく、何をすべきかを伝えたいようです。

問題は、mod1.py を引数としてインタープリターに渡すことによって、モジュールを '__main__' として実行していることです。

PEP 328から:

相対インポートでは、モジュールの __name__ 属性を使用して、パッケージ階層内でのそのモジュールの位置を決定します。モジュールの名前にパッケージ情報が含まれていない場合 (たとえば、'__main__' に設定されている場合)、モジュールが実際にファイル システム上のどこにあるかに関係なく、モジュールが最上位モジュールであるかのように相対インポートが解決されます。

Python 2.6 では、メイン モジュールに関連するモジュールを参照する機能が追加されています。 PEP 366に変更が記載されています。

更新:Nick Coghlan によると、推奨される代替手段は、-m スイッチを使用してパッケージ内でモジュールを実行することです。

于 2008-09-16T14:48:56.873 に答える
150

これが私のために働く解決策です:

as として相対インポートを行い、 from ..sub2 import mod2 実行したい場合mod1.pyは の親ディレクトリに移動しapp、 python -m スイッチ as を使用してモジュールを実行します python -m app.sub1.mod1

この問題が相対インポートで発生する本当の理由は、相対インポートが__name__モジュールのプロパティを取得することによって機能することです。モジュールが直接実行されている場合は、に__name__設定され__main__、パッケージ構造に関する情報は含まれません。relative import in non-packageそして、それがpythonがエラー について不平を言う理由です。

したがって、-m スイッチを使用して、パッケージ構造情報を python に提供し、それによって相対インポートを正常に解決できます。

相対インポートを行っているときに、この問題に何度も遭遇しました。そして、以前の回答をすべて読んだ後でも、定型コードをすべてのファイルに配置する必要なしに、きれいな方法で解決する方法を理解できませんでした。(@ncoghlan と @XiongChiamiov のおかげで、いくつかのコメントは本当に役に立ちました)

PEPを通過するのは本当に楽しいことではないので、これが相対インポートの問題と戦っている人に役立つことを願っています.

于 2013-03-17T07:43:34.060 に答える
128
main.py
setup.py
app/ ->
    __init__.py
    package_a/ ->
       __init__.py
       module_a.py
    package_b/ ->
       __init__.py
       module_b.py
  1. あなたが実行しますpython main.py
  2. main.pyする:import app.package_a.module_a
  3. module_a.pyするimport app.package_b.module_b

あるいは、2 つまたは 3 つを使用できます。from app.package_a import module_a

appPYTHONPATH にある限り、これは機能します。main.pyそれならどこでもいい。

したがってsetup.py、アプリ パッケージ全体とサブパッケージをターゲット システムの python フォルダーとmain.pyターゲット システムのスクリプト フォルダーにコピー (インストール) する を記述します。

于 2009-01-21T12:42:11.840 に答える
51

「Guido は、パッケージ内で実行中のスクリプトをアンチパターンと見なします」(拒否された PEP-3122 )

私は解決策を見つけるのに多くの時間を費やし、Stack Overflow の関連記事を読んで、「もっと良い方法があるに違いない!」と自分に言い聞かせてきました。ないようです。

于 2011-11-19T16:05:29.897 に答える
43

これは 100% 解決されます。

  • アプリ/
    • main.py
  • 設定/
    • local_settings.py

app/main.py に settings/local_setting.py をインポートします。

main.py:

import sys
sys.path.insert(0, "../settings")


try:
    from local_settings import *
except ImportError:
    print('No Import')
于 2016-02-11T12:01:50.573 に答える
26

nosklo's例を挙げた答えの説明

注: すべての__init__.pyファイルは空です。

main.py
app/ ->
    __init__.py
    package_a/ ->
       __init__.py
       fun_a.py
    package_b/ ->
       __init__.py
       fun_b.py

app/package_a/fun_a.py

def print_a():
    print 'This is a function in dir package_a'

app/package_b/fun_b.py

from app.package_a.fun_a import print_a
def print_b():
    print 'This is a function in dir package_b'
    print 'going to call a function in dir package_a'
    print '-'*30
    print_a()

main.py

from app.package_b import fun_b
fun_b.print_b()

実行すると、次のよう$ python main.pyに返されます。

This is a function in dir package_b
going to call a function in dir package_a
------------------------------
This is a function in dir package_a
  • main.py は次のことを行います。from app.package_b import fun_b
  • fun_b.py はfrom app.package_a.fun_a import print_a

so file in folderpackage_bは file in folder を使用しましたpackage_a。これはあなたが望むものです。右??

于 2013-12-08T03:19:42.223 に答える
24
def import_path(fullpath):
    """ 
    Import a file with full path specification. Allows one to
    import from anywhere, something __import__ does not do. 
    """
    path, filename = os.path.split(fullpath)
    filename, ext = os.path.splitext(filename)
    sys.path.append(path)
    module = __import__(filename)
    reload(module) # Might be out of date
    del sys.path[-1]
    return module

このスニペットを使用して、パスからモジュールをインポートしています。

于 2009-07-04T23:27:50.467 に答える
12

残念ながら、これは sys.path のハッキングですが、非常にうまく機能します。

別のレイヤーでこの問題が発生しました。指定された名前のモジュールが既にありましたが、それは間違ったモジュールでした。

私がやりたかったことは次のとおりです(私が作業していたモジュールはmodule3でした):

mymodule\
   __init__.py
   mymodule1\
      __init__.py
      mymodule1_1
   mymodule2\
      __init__.py
      mymodule2_1


import mymodule.mymodule1.mymodule1_1  

既に mymodule をインストールしていますが、私のインストールには "mymodule1" がありません。

インストール済みのモジュールからインポートしようとしていたため、ImportError が発生しました。

sys.path.append を実行しようとしましたが、うまくいきませんでした。機能したのはsys.path.insert でした

if __name__ == '__main__':
    sys.path.insert(0, '../..')

ハックのようなものですが、すべて機能しました。したがって、他のパスをオーバーライドする決定が必要な場合は、sys.path.insert(0, pathname) を使用して機能させる必要があることに注意してください。これは私にとって非常に苛立たしい問題点でした。多くの人が「追加」機能を sys.path に使用すると言っていますが、既にモジュールが定義されている場合は機能しません (非常に奇妙な動作だと思います)。

于 2012-03-02T22:58:47.093 に答える
11

参考までにここに載せておきます。scriptsこれが適切な Python コードではないことはわかっていますが、取り組んでいるプロジェクト用のスクリプトが必要で、そのスクリプトをディレクトリに配置したいと考えていました。

import os.path
import sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
于 2013-01-07T04:26:52.227 に答える
9

.py@EvgeniSergeevがOPへのコメントで述べているように、任意の場所にあるファイルからコードをインポートできます:

import imp

foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()

これは、この SO answerから取得されます。

于 2015-06-09T15:22:27.963 に答える
7

http://docs.python.org/whatsnew/2.5.html#pep-328-absolute-and-relative-importsをご覧ください。あなたができる

from .mod1 import stuff
于 2011-09-24T19:31:57.547 に答える
2

Python docから、

from __future__ import absolute_importPython 2.5 では、ディレクティブを使用してインポートの動作を絶対インポートに切り替えることができます。この絶対インポートの動作は、将来のバージョン (おそらく Python 2.7) でデフォルトになります。絶対インポートがデフォルトにimport stringなると、常に標準ライブラリのバージョンが見つかります。from pkg import stringユーザーは可能な限り絶対インポートを使用することをお勧めします。そのため、コードを書き始めることをお勧めします。

于 2011-06-29T17:33:27.220 に答える
1

John Bが言ったことに加えて、変数を設定すると、他のことを台無しにする可能性がある__package__変数を変更するのではなく、役立つよう__main__です。しかし、私がテストできる限り、完全に機能するわけではありません。

sys.path私は同じ問題を抱えており、PEP 328 または 366 のどちらも問題を完全に解決しません。私が理解できる限り、どちらも 1 日の終わりまでにパッケージの先頭を に含める必要があるためです。

また、これらの変数に入れる文字列をフォーマットする方法が見つからなかったことにも言及する必要があります。それは"package_head.subfolder.module_name"何ですか?

于 2012-09-11T07:47:16.920 に答える
1

「PYTHONPATH」環境変数を最上位フォルダーに設定する方が簡単であることがわかりました。

bash$ export PYTHONPATH=/PATH/TO/APP

それから:

import sub1.func1
#...more import

もちろん、PYTHONPATH は「グローバル」ですが、まだ問題は発生していません。

于 2012-03-17T09:20:09.027 に答える