https://lifesteps.tistory.com/179
이 글 이어서 오류 해결 기록
지긋지긋하게 본 오류:
PermissionError: [WinError 32] 다른 프로세스가 파일을 사용 중이기 때문에 프로세스가 액세스 할 수 없습니다: '[경로]\\apiLog_info_20221024.log' -> '[경로]\\apiLog_info_20221024.log.2022-10-24'
Call stack:
오류 해결한 줄 알았는데, 로컬에서는 내가 자체적으로 서버를 껐다 켜면서 테스트했기 때문에 해결된 것처럼 보인 거였음.
운영은 서버가 계속 돌아가면서 구동되기 때문에 여전히 일별 로그 생성할 때 오류남.
오류 해결해 보려고 참고했던 블로그 :
Error 32가 뜻하는 바도 그렇고 분명 뭔가 멀티프로세스 환경에서 다른 프로세스가 핸들을 물고 있어서 Rotating이 되지 않는 것이 분명했으므로 이를 확인하기 위해 테스트 코드를 짜 봤다.
출처: https://5kyc1ad.tistory.com/269
핸들러의 가장 큰 역할은 목적지 설정이라고 생각하면 됩니다.
getLogger() 는 이름이 제공되는 경우 지정된 이름을 가진 로거 인스턴스에 대한 참조를 반환하고, 그렇지 않으면 root 를 반환합니다. 이름은 마침표로 구분된 계층적 구조입니다. 같은 이름으로 getLogger() 를 여러 번 호출하면 같은 로거 객체에 대한 참조를 반환합니다.
출처: https://yurimkoo.github.io/python/2019/08/11/logging.html
파이썬 logging 라이브러리 자체가 멀티 프로세싱 환경을 고려하지 않고 만들어졌기 때문에 발생한 일이라 간단하게 해결하긴 힘들어 보인다.
출처: https://5kyc1ad.tistory.com/301
동일 모듈 뿐만 아니라, 여러 모듈에서 동일한 인스턴스이름 logging.getLogger('someLogger')를 여러 번 호출해도 동일한 로거 객체에 대한 참조가 반환됩니다.
출처: https://valuefactory.tistory.com/601
웹 서버는 현재 로그 파일(app.log)을 이전 날짜 파일(app.log.yyyy-mm-dd)로 변경한 다음 새로운 로그 파일을 생성하려고 하는데 python 소스 파일이 변경시 감시하는 프로세스가 현재 로그 파일(app.log)을 엑세스하고 있기 때문에 파일 이름을 변경을 하지 못해서 발생하는 오류이다.
출처: https://yscho03.tistory.com/3
delay=True로 바꿔봤는데 안 됨.
참고: https://stackoverflow.com/questions/22459850/permissionerror-when-using-python-3-3-4-and-rotatingfilehandler
원인에 대한 생각:
일단 내가 쓰는 건 log.py로 모듈을 하나 만들어두고 다른 곳에서 전부 이 모듈을 임포트해서 log를 찍는 방식이다.
설정해준 대로 자정이 되면 log 파일 이름을 바꾸고 새 로그 파일을 생성해야 하는데, 로그 파일 이름을 바꿀 때, 이 로그 파일을 누군가가 계속 잡고 있어서 수정하려하면 퍼미션 오류가 나는 것 같다.. 까지는 납득함.
로그 인스턴스 생성 구조가 잘못되었다는 느낌은 받았는데 정확한 이해가 안 돼서 초반에 엄청 난항을 겪었다.
파이썬의 클래스, 객체, 인스턴스에 대한 개념을 다시 공부하고 나서야 원인을 찾을 수 있었다.
샘명의 은인: https://trustyou.tistory.com/70
해결(코드비교):
수정 전
log.py
import logging
from logging.handlers import TimedRotatingFileHandler
def get_logger(name=None):
logger = logging.getLogger(name)
logger.setLevel(logging.INFO)
# log format
formatter = logging.Formatter("%(asctime)s - %(levelname)s - [%(funcName)s:%(lineno)d] - %(message)s")
# handler
console = logging.StreamHandler()
file_handler_info = TimedRotatingFileHandler("[경로]/apiLog_info.log"
, when='midnight', encoding='utf-8', delay=False)
file_handler_error = TimedRotatingFileHandler("[경로]/apiLog_error.log"
, when='midnight', encoding='utf-8', delay=False)
# level 설정
console.setLevel(logging.INFO)
file_handler_info.setLevel(logging.INFO)
file_handler_error.setLevel(logging.ERROR)
# format
console.setFormatter(formatter)
file_handler_info.setFormatter(formatter)
file_handler_error.setFormatter(formatter)
# handler add
logger.addHandler(console)
logger.addHandler(file_handler_info)
logger.addHandler(file_handler_error)
return logger
이런식으로 만들어두고 각 파일에서 log 임포트 해준 다음
import log
logger = log.get_logger("runserver")
logger.info(e)
/
import log
logger = log.get_logger("test")
logger.info("test")
이렇게... 인스턴스를 파일 별로 다 생성해서 쓰는 바람에 오류가 났던 거였음.
수정 후
log.py
import logging
from logging.handlers import TimedRotatingFileHandler
logger = logging.getLogger('log')
logger.setLevel(logging.INFO)
# log format
formatter = logging.Formatter("%(asctime)s - %(levelname)s - [%(funcName)s:%(lineno)d] - %(message)s")
# handler
console = logging.StreamHandler()
file_handler_info = TimedRotatingFileHandler("[경로]/apiLog_info.log"
, when='midnight', encoding='utf-8', delay=False)
file_handler_error = TimedRotatingFileHandler("[경로]/apiLog_error.log"
, when='midnight', encoding='utf-8', delay=False)
# level 설정
console.setLevel(logging.INFO)
file_handler_info.setLevel(logging.INFO)
file_handler_error.setLevel(logging.ERROR)
# format
console.setFormatter(formatter)
file_handler_info.setFormatter(formatter)
file_handler_error.setFormatter(formatter)
# handler add
logger.addHandler(console)
logger.addHandler(file_handler_info)
logger.addHandler(file_handler_error)
이렇게 바꾸고
log.logger.info(e)
이렇게 로그 남겨주니까 로그파일 일별 분리 완전 잘 됨.
파이썬 구조에 대해 제대로 파악하지 않고 따라 개발해서 생긴 일인 것 같다. 객체지향에 대한 공부도 좀 더 필요한듯.
*
파이썬 클래스-인스턴스-객체 / 메서드-생성자 설명 쉽게 잘 쓰여 있는 글
https://wikidocs.net/85
https://kingnamji.tistory.com/6
https://wikidocs.net/28#_2
'기록 > Python' 카테고리의 다른 글
[Python] 파이썬 sys.argv 주의점 (0) | 2022.10.31 |
---|---|
[Python] 파이썬 아이피 형식 맞춰주기 - 0 채워주는 zfill() 함수 (0) | 2022.10.28 |
[Python/Linux] 파이썬 로그 일별 생성 및 주기적으로 삭제 설정 방법 기록 (0) | 2022.10.20 |
[Python] 파이썬 로그 찍는 방법 및 오류 해결 (0) | 2022.10.14 |
[Python] 파이썬 requests.post 에 header 추가 (0) | 2022.10.14 |