HOWTO · Python
Python에서 ImportError: cannot import name을 수정하는 방법
이름, 모듈 경로, 섀도잉, 버전, 순환 임포트를 확인하여 Python의 ImportError: cannot import name을 진단하고, 범위가 지정된 2모듈 수정 방법을 따릅니다.
이 페이지의 내용
ImportError: cannot import name은 Python이 모듈을 찾았지만 요청된 이름을 해당 모듈에서 가져오지 못했다는 뜻입니다. 순환 임포트가 원인 중 하나일 수 있습니다. Python이 한 모듈을 초기화하는 동안 다른 모듈이 아직 바인딩되지 않은 이름을 요청할 수 있기 때문입니다. 철자 오류, 예상과 다른 모듈, 로컬 파일에 의한 섀도잉, 사용할 수 없는 의존성, 패키지/API 버전 불일치도 비슷한 증상을 만들 수 있습니다. (demo1_func1; demo2_func1; demo2_func2)
Python ImportError: cannot import name 오류의 원인
demo1.py와 demo2.py를 생각해 보세요. 각 파일이 모듈 수준에서 from other_module import function을 사용하면, 어느 파일을 임포트하든 초기화가 완료되기 전에 다른 파일의 임포트가 시작됩니다. 특히 두 번째 모듈이 요청할 때는 요청된 함수가 아직 존재하지 않을 수 있습니다. Python은 임포트의 일부로 모듈 수준 문장을 실행합니다. 함수가 나중에 나타날 때까지 기다리지 않습니다.
트레이스백과 임포트 컨텍스트를 이용해 원인을 좁혀 보세요.
- 전체 트레이스백을 읽고 Python이 임포트하지 못한 모듈과 이름을 확인합니다.
- 철자와 대소문자가 해당 모듈의 정의와 일치하는지 확인합니다.
- Python이 실제로 해석하는 파일이 무엇인지 확인합니다. 표준 라이브러리 모듈이나 의존성과 같은 이름의 가까운 파일이 의도한 모듈을 섀도잉할 수 있습니다.
- 패키지가 활성 환경에 설치되어 있고, 그 버전이 코드가 기대하는 API를 제공하는지 확인합니다.
- 이름과 경로가 올바르면 양방향의 모듈 수준 임포트를 추적하여 순환을 찾습니다.
이름 뒤에 오는 정확한 문구는 Python 버전과 임포트 컨텍스트에 따라 달라지므로, 고정된 접미사에 의존하지 말고 트레이스백과 모듈 코드로 진단하세요.
Python ImportError: cannot import name 오류 수정하기
이 2모듈 사례에서는 모듈을 임포트하고 함수가 실행될 때 그 속성을 조회합니다. 이렇게 하면 두 모듈의 임포트가 끝날 때까지 이름 조회를 미룰 수 있습니다. 다음의 자체 완결 예제는 임시 디렉터리에 demo1.py와 demo2.py를 만든 다음 demo2.py를 실행합니다.
from pathlib import Path
import subprocess
import sys
import tempfile
demo1_source = '''import demo2
def demo1_func1():
print("demo1_func1")
demo2.demo2_func2()
'''
demo2_source = '''import demo1
def demo2_func1():
print("demo2_func1")
demo1.demo1_func1()
def demo2_func2():
print("demo2_func2")
if __name__ == "__main__":
demo2_func1()
'''
with tempfile.TemporaryDirectory() as directory:
Path(directory, "demo1.py").write_text(demo1_source, encoding="utf-8")
Path(directory, "demo2.py").write_text(demo2_source, encoding="utf-8")
result = subprocess.run(
[sys.executable, "demo2.py"],
cwd=directory,
text=True,
capture_output=True,
check=True,
)
print(result.stdout, end="")
demo2_func1
demo1_func1
demo2_func2
모듈 임포트로의 변경은 예시된 순환을 해결하는 것이지 보편적인 수정 방법은 아닙니다. 의존성 구조에 따라 공유 함수를 세 번째 모듈로 옮기거나 임포트를 함수 안으로 이동하는 편이 더 명확한 설계일 수 있습니다. 후자는 모듈 범위에서 의존성이 덜 보이게 만듭니다. Blueprint를 사용하는 Flask 애플리케이션은 애플리케이션 임포트를 정리할 때 Flask Blueprint 가이드를 검토하면 도움이 될 수 있습니다.