학습 기록
Python 공부 기록 #22 - configparser 기본값으로 설정 누락에도 멈추지 않게 만들기
0. 목차
- 인트로: 설정 파일을 옮겼더니 자동 실행이 멈췄다
- 설정값이 없으면 어떤 오류가 날까?
read()결과로 설정 파일 확인하기fallback으로 기본값 넣기- 숫자 설정이 잘못됐을 때 처리하기
- 누락과 오류를 로그에 남기기
- 삽질했던 부분들
- 아웃트로: 설정이 달라도 멈추지 않는 코드
1. 인트로: 설정 파일을 옮겼더니 자동 실행이 멈췄다
지난 글에서는 configparser로 파일 경로와 로그 용량을 config.ini에 분리했습니다.
코드를 건드리지 않고 설정만 바꿀 수 있으니 편했습니다. 근데 폴더를 정리하다가 config.ini를 빠뜨린 채 Python 파일만 옮겼더니 작업 스케줄러가 실행되지 않았습니다.
필요한 항목 하나를 잘못 지워도 비슷했습니다. 화면을 보고 직접 실행할 때는 오류를 바로 확인할 수 있지만, 자동 실행은 아침이 돼서야 실패를 알게 되고요.
설정 파일에 문제가 있어도 기본값으로 실행하고, 무엇이 빠졌는지는 로그에 남기면 좋겠다고 생각했습니다.
오늘은 fallback과 예외 처리를 넣어서 설정 누락 때문에 프로그램이 바로 끝나는 일을 막아봤습니다.
2. 설정값이 없으면 어떤 오류가 날까?
먼저 지난 글의 방식으로 없는 설정을 읽어봤습니다.
import configparser
config = configparser.ConfigParser()
config.read("config.ini", encoding="utf-8")
backup_count = config.getint(
"LOG",
"backup_count"
)
[LOG] 구역이 없으면 NoSectionError, backup_count 항목만 없으면 NoOptionError가 발생합니다.
처음에는 설정 파일을 읽었으니 알아서 빈 값이 들어갈 줄 알았습니다. 찾아보니까 configparser는 없는 값을 추측하지 않기 때문에 제가 기본값이나 처리 방법을 정해야 했습니다.
3. read() 결과로 설정 파일 확인하기
read()는 실제로 읽은 설정 파일의 목록을 돌려줍니다.
from pathlib import Path
import configparser
base_dir = Path(__file__).resolve().parent
config_file = base_dir / "config.ini"
config = configparser.ConfigParser()
loaded_files = config.read(
config_file,
encoding="utf-8"
)
if loaded_files:
print("설정 파일을 읽었습니다.")
else:
print("설정 파일이 없어 기본값을 사용합니다.")
파일이 있으면 loaded_files에 경로가 들어가고, 없으면 빈 목록이 됩니다.
config.read()는 파일이 없을 때 바로 오류를 내지 않는다는 점도 처음 알았습니다. 반환값을 확인해야 파일 누락을 구분할 수 있었습니다.
4. fallback으로 기본값 넣기
설정이 없을 때 쓸 값을 fallback에 넣었습니다.
input_file = config.get(
"PATH",
"input_file",
fallback="results/blog_posts.xlsx"
)
max_bytes = config.getint(
"LOG",
"max_bytes",
fallback=5 * 1024 * 1024
)
backup_count = config.getint(
"LOG",
"backup_count",
fallback=5
)
input_file이 있으면 설정 파일의 값을 가져오고, 없으면 results/blog_posts.xlsx를 사용합니다.
숫자도 getint()의 fallback에 정수로 넣을 수 있었습니다. 구역 전체가 없거나 항목 하나가 빠져도 코드가 멈추지 않았습니다. 이거 되겠는데? 싶었습니다.
기본값은 아무 값이나 넣는 것이 아니라, 별도 설정 없이 실행해도 안전한 값으로 정하는 편이 좋았습니다.
5. 숫자 설정이 잘못됐을 때 처리하기
fallback은 설정이 없을 때는 동작하지만, 값의 형식이 잘못된 경우까지 처리하지는 않습니다.
예를 들어 아래 값은 정수로 바꿀 수 없습니다.
[LOG]
backup_count = five
그래서 ValueError를 따로 잡았습니다.
try:
backup_count = config.getint(
"LOG",
"backup_count",
fallback=5
)
except ValueError:
backup_count = 5
print("backup_count 형식 오류, 기본값 5 사용")
항목이 없을 때와 잘못 적었을 때는 다른 상황이었습니다. fallback과 try, except를 같이 쓰니 두 경우를 모두 처리할 수 있었습니다.
6. 누락과 오류를 로그에 남기기
마지막으로 확인 결과를 로그에 기록했습니다.
import configparser
import logging
from pathlib import Path
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s"
)
base_dir = Path(__file__).resolve().parent
config_file = base_dir / "config.ini"
config = configparser.ConfigParser()
loaded_files = config.read(config_file, encoding="utf-8")
if not loaded_files:
logging.warning(
"설정 파일이 없어 기본값을 사용합니다: %s",
config_file
)
input_file = Path(config.get(
"PATH",
"input_file",
fallback="results/blog_posts.xlsx"
))
try:
backup_count = config.getint(
"LOG",
"backup_count",
fallback=5
)
except ValueError:
backup_count = 5
logging.exception(
"backup_count 형식이 잘못되어 기본값 5를 사용합니다."
)
logging.info("입력 파일: %s", input_file)
logging.info("로그 보관 개수: %s", backup_count)
설정 파일이 없으면 WARNING, 숫자 형식이 틀리면 오류 내용과 기본값을 기록합니다.
프로그램은 계속 실행되지만 로그를 보면 어떤 설정이 대신 적용됐는지 알 수 있습니다. 자동 실행에서는 조용히 기본값만 쓰는 것보다 기록을 함께 남기는 편이 확인하기 좋았습니다.
7. 삽질했던 부분들
처음에는 모든 오류를 한꺼번에 잡았습니다.
try:
backup_count = config.getint("LOG", "backup_count")
except Exception:
backup_count = 5
코드는 멈추지 않았지만 설정이 없는지, 숫자를 잘못 적었는지 알 수 없었습니다. 기본값을 쓸 때도 이유를 로그에 남겨야 했습니다.
또 fallback="5"처럼 문자열을 넣었습니다. getint()에서 받을 기본값은 나중에 숫자로 사용할 값이므로 fallback=5처럼 정수로 적는 편이 분명했습니다.
마지막으로 입력 파일 경로까지 무조건 기본값으로 넘겼더니, 엉뚱한 파일을 읽을 수도 있었습니다. 실행을 계속해도 안전한 로그 개수에는 기본값을 쓰고, 꼭 필요한 입력 파일은 exists()로 다시 확인하도록 나눴습니다.
8. 아웃트로: 설정이 달라도 멈추지 않는 코드
오늘은 설정 파일이나 항목이 빠졌을 때 기본값으로 실행하고, 문제 내용을 로그에 남겨봤습니다.
핵심 정리
read()의 반환값으로 설정 파일을 읽었는지 확인하기fallback으로 누락된 항목의 기본값 정하기- 숫자 형식 오류는
ValueError로 따로 처리하기 - 기본값을 사용한 이유를
WARNING과ERROR로 기록하기 - 꼭 필요한 파일은 기본값만 믿지 말고 존재 여부 확인하기
이제 할 수 있는 것들
config.ini가 없어도 안전한 기본 설정으로 실행하기- 일부 설정 항목이 빠져도 자동 작업 이어가기
- 숫자를 잘못 입력한 설정 찾아내기
- 로그에서 실제로 적용된 설정값 확인하기
비전공자 Python 공부를 하다 보니 오류를 없애는 것보다, 문제가 생겼을 때 어디까지 실행할지를 정하는 일이 중요하다는 걸 알게 됐습니다. 직장인 Python 업무 자동화에서는 특히 밤사이 실행이 멈추지 않는 쪽이 마음이 놓였습니다.
다음 포스팅에서는 비밀번호나 API 키처럼 코드와 config.ini에도 그대로 적으면 곤란한 값을 .env 파일과 환경 변수로 분리하는 방법을 공부해 보겠습니다. ChatGPT API나 다른 외부 서비스에 연결하기 전에 알아두면 좋을 것 같습니다.