파이썬 3의 상대적 가져 오기에 대해서는 이미 꽤 많은 질문이 있지만 많은 것들을 거친 후에도 여전히 내 문제에 대한 답을 찾지 못했습니다. 여기 질문이 있습니다.
아래에 표시된 패키지가 있습니다
package/
__init__.py
A/
__init__.py
foo.py
test_A/
__init__.py
test.py
test.py에 한 줄이 있습니다.
from ..A import foo
지금은의 폴더에 package
있으며
python -m test_A.test
나는 메시지를 받았다
"ValueError: attempted relative import beyond top-level package"
그러나 내가 package
예를 들어 의 상위 폴더에 있다면 다음을 실행합니다.
cd ..
python -m package.test_A.test
다 괜찮아
이제 내 질문은 :
의 폴더에있을 때 package
test_A 하위 패키지 내부에서 모듈을 실행합니다 test_A.test
. 내 이해에 ..A
따라 여전히 package
폴더 내에있는 한 수준 만 올라갑니다 beyond top-level package
. 왜 메시지가 나타납니다 . 이 오류 메시지를 발생시키는 이유는 무엇입니까?
답변
편집 : 다른 질문 에이 질문에 대한 더 좋고 더 일관된 답변이 있습니다.
왜 작동하지 않습니까? 파이썬이 패키지가로드 된 위치를 기록하지 않기 때문입니다. 따라서 할 때 python -m test_A.test
기본적으로 test_A.test
실제로 저장된 지식을 버립니다 package
(즉 package
, 패키지로 간주되지 않음). 시도는 from ..A import foo
그것이 더 이상 (로드 된 위치, 즉 형제 디렉토리)이없는 액세스 정보에 노력하고있다. from ..os import path
의 파일 을 허용 하는 것과 개념적으로 비슷합니다 math
. 패키지를 구별하기를 원하기 때문에 이것은 나쁠 것입니다. 다른 패키지의 무언가를 사용해야하는 경우 전 세계적으로 패키지를 참조 from os import path
하고 파이썬이 $PATH
and 와 함께있는 곳에서 작동하도록 해야합니다 $PYTHONPATH
.
을 사용하면 내용을 추적 하고로드 된 위치의 하위 디렉토리에 액세스 하기 때문에 문제 python -m package.test_A.test
를 from ..A import foo
해결하는 것이 package
좋습니다.
파이썬이 현재 작업 디렉토리를 패키지로 간주하지 않는 이유는 무엇입니까? CLUE 는 없지만 유용합니다.
답변
import sys
sys.path.append("..") # Adds higher directory to python modules path.
이 시도. 나를 위해 일했다.
답변
가정 :
당신이있는 경우 package
디렉토리 A
와 test_A
별도의 패키지입니다.
결론 :
..A
가져 오기는 패키지 내에서만 허용됩니다.
추가 참고 사항 :
패키지 내에서만 사용할 수있는 상대 가져 오기를 만드는 것은 패키지를에있는 경로에 강제로 배치하려는 경우에 유용합니다 sys.path
.
편집하다:
나는 이것이 미쳤다고 생각하는 유일한 사람입니까!? 왜 현재 작업 디렉토리가 패키지로 간주되지 않습니까? – 멀티 헌터
현재 작업 디렉토리는 일반적으로 sys.path에 있습니다. 따라서 모든 파일을 가져올 수 있습니다. 이것은 패키지가 아직 존재하지 않은 Python 2 이후의 동작입니다. 실행중인 디렉토리를 패키지로 만들면 모듈을 “import .A”로 가져오고 “import A”로 가져 오면 두 개의 다른 모듈이됩니다. 어쩌면 이것은 일관성이없는 것일 수도 있습니다.
답변
3.6에서 이러한 솔루션 중 어느 것도 다음과 같은 폴더 구조로 작동하지 않았습니다.
package1/
subpackage1/
module1.py
package2/
subpackage2/
module2.py
내 목표는 module1에서 module2로 가져 오는 것이 었습니다. 마침내 나를 위해 일한 것은 이상하게도 충분했습니다.
import sys
sys.path.append(".")
지금까지 언급 한 2 점 솔루션과 달리 단일 점에 유의하십시오.
편집 : 다음은 나를 위해 이것을 명확히하는 데 도움이되었습니다.
import os
print (os.getcwd())
필자의 경우 작업 디렉토리는 (예기치 않게) 프로젝트의 루트였습니다.
답변
from package.A import foo
나는 그것이 더 분명하다고 생각
import sys
sys.path.append("..")
답변
당신은 기본적으로 그 때문에 가장 인기있는 대답에서 알 수 있듯이 PYTHONPATH
또는 sys.path
포함 .
하지만 경로 패키지에. 그리고 상대적 가져 오기는 가져 오기가 발생하는 파일이 아니라 현재 작업 디렉토리에 상대적입니다. 이상하게도
먼저 상대 가져 오기를 절대로 변경 한 다음 시작하여이 문제를 해결할 수 있습니다.
PYTHONPATH=/path/to/package python -m test_A.test
또는 이런 식으로 호출 될 때 파이썬 경로를 강제로 :
으로 python -m test_A.test
당신이 실행하고 test_A/test.py
함께 __name__ == '__main__'
하고__file__ == '/absolute/path/to/test_A/test.py'
즉 , 주요 사례 조건에서 test.py
절대 import
반 보호를 사용하고 일회성 Python 경로 조작을 수행 할 수 있음을 의미합니다 .
from os import path
…
def main():
…
if __name__ == '__main__':
import sys
sys.path.append(path.join(path.dirname(__file__), '..'))
from A import foo
exit(main())
답변
편집 : 2020-05-08 : 내가 인용 한 웹 사이트가 더 이상 조언을 작성한 사람이 제어하지 않는 것 같습니다. 그래서 사이트 링크를 제거하고 있습니다. baxx를 알려 주셔서 감사합니다.
이미 큰 답변을 제공 한 후에도 누군가가 여전히 어려움을 겪고 있다면 웹 사이트에서 더 이상 사용할 수 없다는 조언을 얻었습니다.
내가 언급 한 사이트의 필수 인용문 :
“이 방법으로 프로그래밍 방식으로 동일하게 지정할 수 있습니다.
수입 시스템
sys.path.append ( ‘..’)
물론 위의 코드는 다른 import
문 전에 작성해야합니다 .
그것이 사실 후에 생각하고, 이런 식이어야한다는 것이 분명합니다. 내 테스트에서 sys.path.append ( ‘..’)를 사용하려고했지만 OP가 게시 한 문제가 발생했습니다. 다른 가져 오기 전에 가져 오기 및 sys.path 정의를 추가하여 문제를 해결할 수있었습니다.