누구나 파이썬의 상대적 수입을 설명 할 수 있습니까?


174

나는 내 인생에서 파이썬의 상대적 수입품을 얻을 수 없다. 작동하지 않는 간단한 예를 만들었습니다.

디렉토리 구조는 다음과 같습니다.

/__init__.py
/start.py
/parent.py
/sub/__init__.py
/sub/relative.py

/start.py 단지 포함 : import sub.relative

/sub/relative.py 그냥 포함 from .. import parent

다른 모든 파일은 비어 있습니다.

명령 행에서 다음을 실행할 때 :

$ cd /
$ python start.py

나는 얻다:

Traceback (most recent call last):
  File "start.py", line 1, in <module>
    import sub.relative
  File "/home/cvondrick/sandbox/sub/relative.py", line 1, in <module>
    from .. import parent
ValueError: Attempted relative import beyond toplevel package

Python 2.6을 사용하고 있습니다. 왜 이런 경우입니까? 이 샌드 박스 예제를 어떻게 작동하게합니까?

답변:


140

"sub"패키지에서 가져오고 있습니다. 선물 start.py이 있어도 패키지 자체가 아닙니다 __init__.py.

하나의 디렉토리에서 프로그램을 시작해야합니다 parent.py.

./start.py

./pkg/__init__.py
./pkg/parent.py
./pkg/sub/__init__.py
./pkg/sub/relative.py

start.py:

import pkg.sub.relative

이제 pkg가 최상위 패키지이며 상대 가져 오기가 작동합니다.


현재 레이아웃을 고수하려면을 사용하면 import parent됩니다. start.py인터프리터를 시작 하는 데 사용 하기 때문에 start.py위치가 있는 디렉토리 는 파이썬 경로에 있습니다. parent.py별도의 모듈로 존재합니다.

__init__.py디렉토리 트리 위로 스크립트를 가져 오지 않으면 최상위 레벨을 안전하게 삭제할 수도 있습니다 .


2
'모듈'과 '패키지'라는 용어를 혼동하고 있습니다. 'start.py'는 모듈 'start', 'mod'및 'mod.sub'는 패키지이고 'mod'는 최상위 패키지입니다.
Ferdinand Beyer

34
고마워, 그러나 이것은 정직하게 정말로 어리석은 것처럼 보입니다. 그런 아름다운 언어의 경우 디자이너가 그러한 제한을 만들 것이라고 믿을 수 없습니다. 다른 방법이 없습니까?
carl December

2
전혀 바보가 아닙니다. 상대적 수입은 패키지 내의 형제 모듈을 의미합니다. 최상위 모듈을 가져 오려면 절대 가져 오기를 사용하십시오.
Ferdinand Beyer

58
바보 아니야? bash에서 ".."로 상대 상위 디렉토리를 처리 할 수 ​​있지 않습니까?
e-satis

2
파이썬의 아이디어는 부모 스크립트를 시작한 디렉토리에서 "절대"가져 오기를 사용하는 것 같습니다. 따라서 절대 경로 "import parent"를 사용하여 형제에서 상위 모듈을 가져올 수 있습니다. 그리고 친척은 어떤 종류의 유산이나 다른
Odysseus

35

relative.py직접 호출 하려는 경우, 즉 최상위 모듈에서 실제로 가져 오려면 명시 적으로 sys.path목록에 추가해야 합니다.
작동 방식은 다음과 같습니다.

# Add this line to the beginning of relative.py file
import sys
sys.path.append('..')

# Now you can do imports from one directory top cause it is in the sys.path
import parent

# And even like this:
from parent import Parent

위의 내용으로 인해 불일치가 발생할 수 있다고 생각되면 대신 사용할 수 있습니다.

sys.path.append(sys.path[0] + "/..")

sys.path[0] 진입 점이 실행 된 경로를 나타냅니다.


3

python3에서 확인하기 :

python -V
Python 3.6.5

예 1 :

.
├── parent.py
├── start.py
└── sub
    └── relative.py

- start.py
import sub.relative

- parent.py
print('Hello from parent.py')

- sub/relative.py
from .. import parent

우리가 이것을 이렇게 실행하면 (PYTHONPATH가 비어 있는지 확인하십시오) :

PYTHONPATH='' python3 start.py

산출:

Traceback (most recent call last):
  File "start.py", line 1, in <module>
    import sub.relative
  File "/python-import-examples/so-example-v1/sub/relative.py", line 1, in <module>
    from .. import parent
ValueError: attempted relative import beyond top-level package

수입을 바꾸면 sub/relative.py

- sub/relative.py
import parent

다음과 같이 실행하면 :

PYTHONPATH='' python3 start.py

산출:

Hello from parent.py

예 2 :

.
├── parent.py
└── sub
    ├── relative.py
    └── start.py

- parent.py
print('Hello from parent.py')

- sub/relative.py
print('Hello from relative.py')

- sub/start.py
import relative
from .. import parent

다음과 같이 실행하십시오.

PYTHONPATH='' python3 sub/start.py

산출:

Hello from relative.py
Traceback (most recent call last):
  File "sub/start.py", line 2, in <module>
    from .. import parent
ValueError: attempted relative import beyond top-level package

다음에서 가져 오기를 변경하면 sub/start.py:

- sub/start.py
import relative
import parent

다음과 같이 실행하십시오.

PYTHONPATH='' python3 sub/start.py

산출:

Hello from relative.py
Traceback (most recent call last):
  File "sub/start.py", line 3, in <module>
    import parent
ModuleNotFoundError: No module named 'parent'

다음과 같이 실행하십시오.

PYTHONPATH='.' python3 sub/start.py

산출:

Hello from relative.py
Hello from parent.py

또한 루트 폴더에서 가져 오기를 사용하는 것이 좋습니다.

- sub/start.py
import sub.relative
import parent

다음과 같이 실행하십시오.

PYTHONPATH='.' python3 sub/start.py

산출:

Hello from relative.py
Hello from parent.py
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.