[태그:] Python

  • 윈도우 작업 스케줄러: 스크립트 상대 경로 오류 해결

    윈도우 작업 스케줄러를 사용하여 Python 스크립트를 자동화하는 과정에서 생겼던 작은 이슈인데, 다음과 같이 해결하였다.

    문제:
    스크립트와 동일한 디렉토리에 위치한 외부 리소스 파일(CSV, JSON, 설정 파일 등)을 로드하지 못하고 FileNotFoundError가 발생하는 현상.

    원인 분석:
    이 문제는 실행 컨텍스트상의 현재 작업 디렉토리와 스크립트의 실제 물리적 경로가 일치하지 않아 발생한다.

    • 기본 동작 : 윈도우 작업 스케줄러는 작업을 실행할 때, 별도의 설정이 없으면 작업 디렉토리를 스크립트 위치가 아닌 시스템 기본 경로, 즉 (C:\Windows|System32)로 초기화한다.
    • 경로 참조 실패 : 이로 인해 코드 내에서 사용된 상대 경로는 스크립트가 있는 폴더가 아닌 System32 폴더를 참조하게 되며, 해당 위치에는 파일이 존재하지 않게 되는 것이다.


    해결 방안:
    스크립트가 실행되는 동안의 작업 디렉토리를 스크립트 파일이 위치한 경로와 일치시켜야 한다.

    • 설정 방법 : 작업 스케줄러 속성 상의 동작 탭 -> 편집 메뉴 진입.
    • 조치 사항 : 시작 위치 필드에 실행할 스크립트 파일이 저장된 폴더의 절대 경로를 입력.
    • 결과 : 스크립트 실행 시점의 CWD가 지정된 폴더로 고정되므로, 코드 수정 없이도 상대 경로를 통한 리소스 파일 접근이 정상적으로 작동한다.


    요약:
    윈도우 작업 스케줄러 작업 구성시, ‘실행 파일’의 경로 뿐만 아니라 실행의 기준이 되는 ‘시작 위치’를 반드시 명시해야 한다.

    ex)
    [참고: 실행 경로 비교 예시]
    :x: 설정 전 (오류 발생)

    • 실행 위치 (CWD):C:\\Windows\\System32
    • 스크립트 요청:read("file.csv") (상대 경로)
    • 실제 탐색 경로:C:\\Windows\\System32\\file.csv
    • 결과:File Not Found (파일 없음)

    :white_check_mark: 설정 후 (정상 작동)

    • 시작 위치 설정:E:\\Project
    • 실행 위치 (CWD):E:\\Project
    • 스크립트 요청:read("file.csv") (상대 경로)
    • 실제 탐색 경로:E:\\Project\\file.csv
    • 결과:Success (파일 찾음)

  • Python Logger

    1. Logger

    어떤 프로그램이 실행될 때 발생하는 이벤트를 추적, 로그를 출력한다.

    1) Log Levels

    기본 수준은 WARNING.

    (1) DEBUG(10):   자세한 정보를 갖고 있는 로그. 문제 해결시 필요하면 사용.

    (2) INFO(20): 프로그램이 예상대로 정상 작동되고 있는지 확인할 때 사용

    (3) WARNING(30): 예상치 못한 일이 발생, 또는 추후 발생할 문제를 표시. 작업은 정상 진행.

    (4) ERROR(40): 심각한 문제로 인해 프로그램이 일부 기능을 수행하지 못하고 의도한 정상 기능에 도달하지 못함

    (5) CRITICAL(50): 더욱심각한 문제로 프로그램 자체가 실행이 얼마든지 중단될 수 있음을 알림.

    1. Logger 사용법

    1) Log level

    • 모든 로그를 출력하기 위해 Log level을 DEBUG로 설정.
    import logging
    
    logging.basicConfig(level=logging.DEBUG)
    logging.debug('View all logs')

    2) Log Formatting

    로그 이벤트의 출력 format을 설정.

    • 로그에 현재 날짜와 시간, 로그 level, 로그 메시지 출력
    import logging
    
    logging.basicConfig(format='%(asctime)s %(levelname)s:%(message)s',
                        datefmt='%m/%d/%Y %I:%M:%S %p',
                        level=logging.DEBUG)
    
    logging.debug('view all logs.')

    3) Logging

    (1) Logger 생성

    import logging
    
    log = logging.getLogger("test")

    (2) Logger Level 설정

    생성한 로거 인스턴스에 각각 로그 level  지정, 설정하지 않을 시 default 값 WARNING

    import logging
    
    log = logging.getLogger("test")
    
    #Logging Level 설정
    log.setLevel(logging.DEBUG)

    (3) Handler 설정

    콘솔창에 출력할지·파일로 로그를 기록할지 설정 가능.

    • StreamHandler(): 콘솔 출력
    streamHandler = logging.StreamHandler()
    log.addHandler(streamhandler)
    • FileHandler(): 파일 출력
    filehandler = logging.FileHandler('test.log')
    log.addHandler(filehandler)

    (4) Formatting 설정

    import logging
    
    log = logging.getLogger("test")
    
    log.setLevel(logging.DEBUG)
    
    # Logging Formatting
    formatter = logging.Formatter('%(asctime)s %(levelname)s: %(message)s')
    
    streamhandler = logging.StreamHandler()
    streamhandler.setFormatter(formatter)
    log.addHandler(streamhandler)
    
    log.debug('view all logs')