파이썬 configparser 오류, 파일·섹션·옵션·보간을 구분해 진단하는 법

파이썬 configparser 오류는 먼저 파일이 실제로 읽혔는지 확인한 뒤 섹션, 옵션, 보간 순서로 좁혀야 합니다. read()의 반환값이 빈 목록이면 파일 경로나 파일명 문제를 먼저 보고, 파일이 읽혔다면 NoSectionError, NoOptionError, InterpolationSyntaxError를 구분해 확인합니다. 설정의 %를 그대로 읽어야 한다면 보간을 끄는 선택도 가능하지만, 필수 설정 누락을 기본값으로 조용히 넘겨도 되는지는 별도로 판단해야 합니다.

오류를 예외 이름만으로 고치지 않는 이유

자동화 작업에서 설정값을 읽지 못하면 코드의 try/except부터 넓게 감싸기 쉽습니다. 그러나 파일 자체가 로드되지 않은 경우와 파일은 읽혔지만 요청한 섹션이나 옵션이 없는 경우는 수정할 위치가 다릅니다. 예외를 없애는 것보다 설정 파일과 코드 중 어디를 고쳐야 하는지 먼저 나누는 편이 안전합니다.

첫 단계: 파일이 읽혔는지 확인하기

ConfigParser.read()는 성공적으로 읽고 파싱한 파일명 목록을 반환합니다. 따라서 파일을 읽었다고 가정하지 말고 반환값을 확인합니다.

import configparser

config = configparser.ConfigParser()
loaded_files = config.read("settings.ini", encoding="utf-8")

if not loaded_files:
    raise FileNotFoundError("settings.ini를 읽지 못했습니다.")

빈 목록이면 상대 경로의 기준이 실행 위치와 다르거나 파일명이 틀렸을 가능성을 먼저 확인합니다. 이 단계에서 has_section()을 호출해도 파일이 없다는 사실을 해결해 주지는 않습니다.

두 번째 단계: 섹션과 옵션을 분리해 확인하기

파일이 읽힌 뒤에는 설정 파일의 섹션과 코드가 요청한 옵션을 따로 봅니다. sections()는 DEFAULT를 제외한 섹션을 보여 주고, has_section()은 지정한 섹션의 존재 여부를, has_option()은 그 섹션에서 옵션을 찾을 수 있는지를 확인합니다.

section = "database"
option = "host"

if not config.has_section(section):
    raise ValueError(f"필수 섹션이 없습니다: {section}")
if not config.has_option(section, option):
    raise ValueError(f"필수 옵션이 없습니다: {section}.{option}")

host = config.get(section, option)

NoSectionError는 없는 섹션을 지정했을 때, NoOptionError는 지정한 섹션에 없는 옵션을 조회할 때 발생합니다. 섹션 이름의 오타인지 옵션 이름의 오타인지가 다르므로 두 예외를 한 메시지로 뭉개지 않는 것이 좋습니다.

옵션 대소문자와 DEFAULT를 확인하기

기본 optionxform()은 옵션명을 소문자로 바꾸므로 Host와 host를 구분해야 하는 설정이라면 코드와 파일 양쪽의 기대가 어긋날 수 있습니다. 대소문자를 보존해야 할 때는 파서를 만들고 optionxform = str을 설정한 뒤 읽기·조회 방식까지 일관되게 맞춥니다.

config = configparser.ConfigParser()
config.optionxform = str

DEFAULT에 둔 값은 섹션에서 사용할 수 있고, get()의 fallback보다 우선합니다. 따라서 기본값이 있다는 이유만으로 필수 설정이 검증됐다고 보기는 어렵습니다. 실행에 반드시 필요한 값이라면 존재 여부와 허용 가능한 값인지 확인한 뒤 진행하는 편이 낫습니다.

값의 퍼센트 기호와 보간 오류 구분하기

ConfigParser는 기본적으로 보간을 사용합니다. 값에 보간 문법으로 해석될 수 없는 %가 들어가면 InterpolationSyntaxError가 발생할 수 있으므로, 비밀번호나 템플릿처럼 퍼센트 자체가 값인 항목인지 먼저 확인합니다.

보간이 필요한 설정이면 INI 값의 보간 문법을 고치는 것이 우선입니다. 파일의 값을 보간 없이 그대로 다루어야 하는 경우에는 파서 전체에서 보간을 끄거나 특정 조회에서만 원시 값을 요청할 수 있습니다.

raw_config = configparser.ConfigParser(interpolation=None)
raw_config.read("settings.ini", encoding="utf-8")

value_without_interpolation = raw_config.get("app", "template")

RawConfigParser도 보간이 기본적으로 비활성화된 파서입니다. 다만 보간을 끄면 다른 값의 참조가 자동으로 해석되지 않으므로, 보간이 필요했던 설정의 동작까지 바뀌지 않는지 확인해야 합니다. 한 번의 조회만 원시 값으로 읽는 상황이라면 get(raw=True)가 범위가 더 좁은 선택입니다.

ConfigParser, RawConfigParser, fallback 중 선택 기준

ConfigParser는 일반적인 INI 설정과 보간을 함께 사용할 때 기본 선택입니다. 값의 %를 해석하지 않고 그대로 보관해야 하면 ConfigParser(interpolation=None) 또는 RawConfigParser를 검토합니다. fallback은 해당 옵션이 없을 때 대체값을 제공하는 기능이지, 필수 설정이 존재하는지 검증하는 기능은 아닙니다.

운영에 필요한 선택은 다음처럼 정리할 수 있습니다.

  • 파일이 읽히지 않으면 경로와 실행 위치를 수정합니다.
  • 섹션이 없으면 INI의 섹션 이름과 코드의 요청 이름을 맞춥니다.
  • 옵션이 없으면 키 이름, 대소문자 변환, DEFAULT 사용 여부를 확인합니다.
  • %가 실제 값이면 보간을 유지할지, 끌지, 한 번의 조회만 원시 처리할지 결정합니다.
  • 필수값이면 fallback으로 숨기지 말고 누락 시 실행을 중단할지 정합니다.

마무리: 예외를 숨기기 전에 확인할 순서

파이썬 configparser 오류를 만났을 때의 핵심 순서는 read() 결과, 섹션, 옵션, 옵션 변환과 DEFAULT, 마지막으로 보간입니다. 이 순서라면 파일 미로드와 NoSectionError·NoOptionError, 퍼센트 값에 의한 InterpolationSyntaxError를 같은 문제로 취급하지 않게 됩니다. 설정값의 성격과 자동화의 실패 비용을 기준으로 기본값과 보간 해제 범위를 정한 뒤, 필수 설정이 빠졌을 때는 조용히 진행하지 않는 쪽이 운영상 안전합니다.

Python으로 자동화 흐름을 만들면서 JSON 결과의 형식 검증도 함께 다룬다면 파이썬 AI JSON 응답 오류 줄이기: JSON 모드와 Structured Outputs, Pydantic 검증 구분법도 이어서 확인할 수 있습니다.

출처

Leave a Comment