A A
[Python] Logging (로깅) & 정규 표현식

Logging (로깅)

로깅은 프로그램 실행 중 발생하는 사건들을 기록하여 디버깅, 오류 추적, 시스템 모니터링 등을 보조하는 행위입니다.
  • 로깅을 통해 코드의 실행 흐름과 상태를 파악할 수 있으며, 시스템의 상태를 실시간으로 모니터링하여 문제 발생 시 빠르게 대응할 수 있습니다.

Logging Module

Python의 logging 모듈은 표준 라이브러리로 제공되며, 다양한 로그 메시지를 기록할 수 있는 유연한 로깅 시스템을 제공합니다.

 

  • Logger: 로그 메시지를 기록하는 인터페이스입니다. 애플리케이션 코드에서 직접 호출됩니다.
  • Handler: 로그 메시지를 특정 대상(파일, 콘솔 등)으로 전송합니다.
  • Formatter: 로그 메시지의 형식을 지정합니다.
  • Level: 로그 메시지의 중요도를 나타냅니다. (DEBUG, INFO, WARNING, ERROR, CRITICAL)

 

Logging - 로깅 설정방법 (기본 로깅 설정)

basicConfig 함수

basicConfig 함수를 사용하여 간단한 로깅 설정을 수행할 수 있습니다.
import logging

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message')

Logger 객체를 직접 설정

Logger, Handler, Formatter 객체를 직접 생성하고 설정할 수 있습니다.
import logging

# Logger 생성
logger = logging.getLogger('my_logger')
logger.setLevel(logging.DEBUG)

# Handler 생성 (콘솔 출력)
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)

# Formatter 생성
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)

# Logger에 Handler 추가
logger.addHandler(console_handler)

# 로그 메시지 출력
logger.debug('This is a debug message')
logger.info('This is an info message')
logger.warning('This is a warning message')
logger.error('This is an error message')
logger.critical('This is a critical message')

설정 파일 사용 (INI, JSON, YAML 등)

설정 파일을 사용하여 로깅 설정을 정의하고, 이를 fileConfig, dictConfig 함수를 사용하여 로드할 수 있습니다.
  • Example - INI 파일 사용
  • logging_config.ini 파일
[loggers]
keys=root

[handlers]
keys=consoleHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
  • Python 코드
import logging
import logging.config

logging.config.fileConfig('logging_config.ini')

logger = logging.getLogger('root')
logger.debug('This is a debug message')

예외 처리와 로깅

프로그램 실행 중 발생하는 예외를 로깅하여 디버깅과 문제 해결을 용이하게 할 수 있습니다.
import logging

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

def divide(a, b):
    try:
        return a / b
    except ZeroDivisionError as e:
        logging.error("Attempted to divide by zero", exc_info=True)

divide(10, 0)

로깅의 용도

 

  • 디버깅 및 문제 해결:
    • 로그 메시지를 통해 코드의 실행 흐름과 상태를 파악할 수 있어 디버깅이 용이합니다.
  • 시스템 모니터링:
    • 시스템의 상태를 실시간으로 모니터링하여 문제 발생 시 빠르게 대응할 수 있습니다.
  • 분석 및 감사:
    • 로그 기록을 통해 중요한 사건이나 트랜잭션을 추적하고 분석하여 감사와 보고에 활용할 수 있습니다.

정규 표현식 (Regular expression)

정규표현식은 문자열에서 특정 패턴을 찾기 위해 사용하는 표현식입니다.

  • 이를 통해 문자열 검색, 매칭, 치환, 추출 등 다양한 작업을 간단하고 효율적으로 수행할 수 있습니다.

 

정규표현식의 주요 용도

 

  • 데이터 유효성 검사: 이메일 주소, 전화번호, 우편번호 등의 형식을 검사할 때 사용합니다.
  • 데이터 추출: 문자열에서 필요한 부분만 추출할 때 사용합니다.
  • 데이터 변환: 특정 패턴을 다른 패턴으로 치환할 때 사용합니다.

re 모듈

Python에서 정규표현식을 처리하기 위해 re 모듈을 사용합니다.

주요 함수

  • re.match(): 문자열의 시작에서 패턴을 매칭합니다.
import re
pattern = r'^Hello'
text = 'Hello, world!'
match = re.match(pattern, text)
if match:
    print("Match found")
else:
    print("Match not found")
  • re.search(): 문자열 전체에서 패턴을 매칭합니다.
pattern = r'world'
text = 'Hello, world!'
search = re.search(pattern, text)
if search:
    print("Search found")
else:
    print("Search not found")
  • re.findall(): 매칭되는 모든 패턴을 리스트로 반환합니다.
pattern = r'\d+'
text = 'There are 3 cats, 4 dogs, and 5 birds.'
found = re.findall(pattern, text)
print(found)  # Output: ['3', '4', '5']
  • re.sub(): 매칭되는 패턴을 치환합니다.

 

 

pattern = r'\d+'
replacement = '#'
text = 'There are 3 cats, 4 dogs, and 5 birds.'
new_text = re.sub(pattern, replacement, text)
print(new_text)  # Output: 'There are # cats, # dogs, and # birds.'​

그룹핑과 캡처

괄호를 사용하여 패턴을 그룹화하고 캡처할 수 있습니다.
  • Example: (abc): abc 패턴을 그룹으로 캡처, (\d{3})-(\d{2})-(\d{4}): 전화번호 형식 캡처
pattern = r'(\d{3})-(\d{2})-(\d{4})'
text = '123-45-6789'
match = re.match(pattern, text)
if match:
    print(match.groups())  # Output: ('123', '45', '6789')

비캡쳐 그룹

캡처하지 않는 그룹을 정의하려면 (?:...) 형식을 사용합니다.
  • Example:(? : abc): abc 패턴을 그룹으로 묶지만 캡처하지 않음
pattern = r'(?:abc)'
text = 'abc'
match = re.match(pattern, text)
if match:
    print("Match found")  # Output: Match found

긍정형 전방탐색

패턴의 앞부분을 확인하지만 매칭에서 제외하는 경우에 사용합니다.
  • Example:((? = ...)) \d(? = dollars): 숫자 뒤에 dollars가 오는 경우
pattern = r'\d(?= dollars)'
text = '20 dollars'
search = re.search(pattern, text)
if search:
    print("Positive lookahead found")  # Output: Positive lookahead found

부정형 전방탐색

패턴의 앞부분을 확인하지 않고 매칭에서 제외하는 경우에 사용합니다.
  • Example:((?! …)) \d(?! dollars): 숫자 뒤에 dollars가 오지 않는 경우
pattern = r'\d(?! dollars)'
text = '20 euros'
search = re.search(pattern, text)
if search:
    print("Negative lookahead found")  # Output: Negative lookahead found