파이썬 환경변수가 안 읽힐 때: os.getenv·.env·예약 실행 확인법

파이썬에서 환경변수가 안 읽힐 때는 코드 한 줄보다 실행 프로세스가 어떤 환경을 받았는지부터 확인해야 합니다. os.getenv()가 None을 반환하면 환경변수 이름과 실행 방식, .env 로드 경로, 자식 프로세스 전달 여부를 차례로 나눠 보세요. API 키 값 자체는 로그에 출력하지 않습니다.

먼저 os.getenv()가 읽는 대상을 확인합니다

os.getenv("SERVICE_TOKEN")은 현재 Python 프로세스의 환경을 읽습니다. 터미널에서 실행할 때는 값이 있는데 IDE나 예약 실행에서 None이면, 두 실행이 같은 환경을 받는다고 가정하면 안 됩니다.

확인용 출력은 비밀값 대신 존재 여부만 남기는 편이 안전합니다.

import os

name = "SERVICE_TOKEN"
print({"name": name, "present": bool(os.getenv(name))})

환경변수 이름의 대소문자와 철자, 값을 설정한 셸과 실제 Python을 실행한 프로세스가 같은지부터 확인합니다.

.env는 파일 위치와 우선순위를 분리해서 봅니다

개발 환경에서 python-dotenv를 사용한다면 .env가 실제로 어느 파일인지 명시하는 편이 안전합니다. load_dotenv()는 .env 값을 환경에 올리지만 기본적으로 이미 존재하는 환경변수를 덮어쓰지 않습니다. 기존 환경을 덮어쓸 필요가 있다면 override를 코드에 명시하고 그 이유를 남겨야 합니다.

import os
from pathlib import Path
from dotenv import load_dotenv

env_path = Path(__file__).resolve().parent / ".env"
loaded = load_dotenv(env_path)

print({"dotenv_loaded": loaded, "service_token_present": bool(os.getenv("SERVICE_TOKEN"))})

.env 파일이 없거나 경로가 다르면 load_dotenv()를 호출해도 기대한 값이 생기지 않습니다. dotenv_values()처럼 환경을 직접 바꾸지 않고 파일 내용을 사전으로 읽는 방법도 있으므로, 설정을 합칠 때는 로드 방식과 우선순위를 먼저 결정하세요.

subprocess에는 필요한 환경을 명시합니다

자식 프로세스를 실행할 때 부모 환경을 그대로 기대하면 실행 방식에 따라 차이가 생길 수 있습니다. 부모 환경을 복사한 뒤 필요한 값만 추가해 env로 전달하면 어떤 설정을 넘기는지 코드에서 확인할 수 있습니다.

import os
import subprocess

child_env = os.environ.copy()
child_env["JOB_MODE"] = "scheduled"

subprocess.run(
    ["python", "worker.py"],
    env=child_env,
    check=True,
)

비밀값을 명령줄 인자나 소스 코드에 직접 넣지 말고, 자식 프로세스에도 필요한 범위만 환경으로 전달합니다.

예약 실행에서는 인터프리터와 환경을 같이 점검합니다

예약 실행은 대화형 셸과 다른 프로세스로 시작될 수 있습니다. 실행 명령에 프로젝트의 Python 인터프리터를 명시하고, .env를 쓴다면 코드에서 기준 경로를 분명히 하세요. 먼저 다음 네 가지를 확인하면 됩니다.

  • 실행 파일이 기대한 가상환경의 Python인지 확인합니다.
  • 예약 실행 설정에 필요한 환경변수가 실제로 전달되는지 확인합니다.
  • .env의 기준 경로가 예약 실행의 현재 폴더에 우연히 의존하지 않는지 확인합니다.
  • 실패 로그에는 값이 아니라 변수 이름과 존재 여부만 남깁니다.

가상환경 문제와 환경변수 문제는 구분해야 합니다. python이 다른 인터프리터를 가리키면 패키지 로드가 실패할 수 있지만, 패키지가 정상이어도 프로세스에 환경변수가 전달되지 않으면 os.getenv()는 비어 있을 수 있습니다.

확인 순서를 고정하면 무작정 재시도하지 않아도 됩니다

운영에서 값이 비어 있으면 API를 반복 호출하기 전에 ① 현재 프로세스의 변수 존재 여부, ② .env 절대 기준 경로와 로드 결과, ③ override 우선순위, ④ subprocess의 env, ⑤ 예약 실행의 Python 경로 순서로 확인하세요. 개발용 .env와 운영용 OS 환경변수 중 어느 것을 기준으로 할지도 먼저 정해야 합니다.

환경변수와 비밀값은 코드와 Git에 저장하지 않습니다. 이 글의 예제 출력도 실제 값이 아니라 존재 여부만 보여 주는 mock·진단 형태입니다.

환경변수가 전달되지 않으면 API를 반복 호출하기 전에 공급원과 전달 경로를 먼저 고칩니다.

터미널에서는 되는데 예약 실행에서 안 되는 상황은 프로세스 환경부터 역추적합니다.

출처

Leave a Comment