본문으로 건너뛰기
개발 머꼬
개발 노트Python
hohyeon.dev18

email.py를 만들었더니 관계없는 라이브러리가 ImportError로 죽은 이유

  • #Debugging
  • #Engineering Note
  • #Python

문제 발생

메일 발송 헬퍼를 email.py로 만든 뒤부터 전혀 상관없는 곳이 깨졌습니다.

ImportError: cannot import name 'message_from_string' from 'email' (/app/email.py)

__pycache__를 지워도, 가상환경을 다시 만들어도 같았습니다. 그런데 다른 디렉터리에서 같은 코드를 실행하면 멀쩡했습니다.

원인 분석

내 파일이 표준 라이브러리를 가렸습니다. Python 문서는 모듈 검색 순서를 이렇게 설명합니다 — 인터프리터는 먼저 내장 모듈을 찾고, 그다음 sys.path의 디렉터리들을 뒤집니다. 그리고 sys.path실행 중인 스크립트가 있는 디렉터리(파일이 지정되지 않았으면 현재 디렉터리), PYTHONPATH, 설치 환경 기본값 순으로 초기화됩니다.

문서의 경고가 정확히 이 상황입니다 — 실행 중인 스크립트가 있는 디렉터리는 표준 라이브러리 경로보다 앞, 검색 경로의 맨 앞에 놓입니다. 즉 그 디렉터리의 스크립트가 라이브러리 디렉터리의 같은 이름 모듈 대신 로드됩니다. 의도한 대체가 아니라면 이것은 오류입니다.

import email을 직접 쓰지 않았는데도 깨진 이유는, 우리가 쓰는 라이브러리 내부가 표준 email을 import하기 때문입니다. 이름 하나를 가로채면 그 아래 전부가 영향을 받습니다.

해결 방안

  1. 이름을 바꿉니다. 가장 확실한 해결입니다.
email.py     →  mailer.py
logging.py   →  log_config.py
types.py     →  domain_types.py

자주 겹치는 이름: email, logging, types, json, random, select, queue, copy, test, secrets, token, platform, code.

  1. 어느 파일이 로드됐는지 직접 확인합니다. 추측하지 말고 경로를 봅니다.
import email
print(email.__file__)   # /app/email.py 면 가려진 것
  1. 패키지 구조로 감쌉니다. 모든 코드를 src/myapp/ 아래 패키지로 두고 from myapp import mailer로 부르면, 최상위 이름 공간을 오염시키지 않습니다.

  2. __pycache__의 잔재도 확인합니다. 소스를 지웠는데 .pyc만 남아 계속 잡히는 경우가 있습니다.

  3. 오류 메시지의 괄호를 읽습니다. from 'email' (/app/email.py)처럼 실제 로드된 경로가 이미 적혀 있습니다. 이 한 줄만 봤으면 몇 시간을 아꼈을 종류의 문제입니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.