61326


# 疑問

pythonでは従兄弟のパッケージをインポートしようとするならば、

[code]

    import sys
    sys.path.append('..')
    
[/code]

のような形で親階層のパスを通してやる必要がありますが、パスの追加無しに親階層パッケージのインポートが出来ているような例が見つかったので質問しました。

# ディレクトリ構成

[code]

    .
    ├── pkg_a
    │   ├── __init__.py
    │   └── cls_a.py
    ├── pkg_b
    │   ├── __init__.py
    │   └── cls_b.py
    └── run.py
    
[/code]

# ファイル内容

pkg_a/__init__.py

[code]

    from .cls_a import ClsA
    
[/code]

pkg_a/cls_a.py

[code]

    class ClsA:
        @staticmethod
        def hello():
            print('Hello Cls A')
    
[/code]

pkg_b/__init__.py

[code]

    from .cls_b import ClsB
    
[/code]

**pkg_b/cls_b.py**

[code]

    from pkg_a import ClsA
    
    class ClsB:
        @staticmethod
        def hello():
            ClsA.hello()
            print('Hello Cls B')
    
[/code]

run.py

[code]

    from pkg_b import ClsB
    
    ClsB.hello()
    
[/code]

# 説明

**cls_b.py**
はcls_a.pyをインポートしていますが、階層的に言えばcls_b.pyはcls_a.pyが存在している親階層のパッケージを参照していることになり、本来不可能なことだと思います。

しかし、run.pyを実行すると以下のような結果となり、cls_a.pyは参照されています。

[code]

    > python run.py 
    Hello Cls A
    Hello Cls B
    
[/code]

cls_b.pyからcls_a.pyへの参照が成功している理由を教えて下さい。


CC BY-SA 4.0
2019-12-11T02:19:42.957
61324
2019-12-11T02:58:10.720
9616
question
python python3
親階層のパッケージをパス追加無しでimport出来てしまう


[`sys.path`](https://docs.python.org/ja/3/library/sys.html#sys.path)は現在実行しているモジュールではなく、Python
インタプリタを起動したスクリプトのあるディレクトリが重要です。

もし`run.py`を`pkg_b`の下にこのように移動して実行すると、`ModuleNotFoundError`とエラーが発生する。

[code]

    $ cat pkg_b/run.py 
    from cls_b import ClsB
    
    ClsB.hello()
    
    $ tree
    .
    ├── pkg_a
    │   ├── __init__.py
    │   └── cls_a.py
    └── pkg_b
        ├── __init__.py
        ├── cls_b.py
        └── run.py
    
    $ cd pkg_b; python3 run.py 
    Traceback (most recent call last):
      File "run.py", line 1, in <module>
        from cls_b import ClsB
      File "~/pkg_b/cls_b.py", line 1, in <module>
        from pkg_a import ClsA
    ModuleNotFoundError: No module named 'pkg_a'
    
[/code]

親階層のパスを通すと、また成功する。

[code]

    $ cat run.py 
    import sys
    sys.path.append("..")
    
    from cls_b import ClsB
    
    ClsB.hello()
    
    $ python3 run.py 
    Hello Cls A
    Hello Cls B
    
[/code]


CC BY-SA 4.0
2019-12-11T02:58:10.720
61326
2019-12-11T02:58:10.720
37023
61324
answer