<aside>
</aside>
μλ
νμΈμ, μ½λ νμ μ¬λ¬λΆ! π΅οΈ μ§λλ² @logger.catchλ₯Ό ν΅ν΄ loguruκ° μΌλ§λ μμΈν μμΈ λ³΄κ³ μλ₯Ό λ§λ€μ΄μ£Όλμ§ κ²½ννμ£ ? μ΄λ² μ±ν°μμλ κ±°κΈ°μ ν κ±Έμ λ λμκ°, μμΈκ° λ°μν μκ°μ λͺ¨λ κ²μ μμλ€μ΄ νν€μΉλ λ κ°μ§ κ°λ ₯ν λλ²κΉ
λꡬ, backtraceμ diagnose μ΅μ
μ λ°°μλ³΄κ² μ΅λλ€.
μ΄ μ΅μ
λ€μ logger.add()λ‘ μ±ν¬λ₯Ό μ€μ ν λ μΆκ°νλ κ²μΌλ‘, λ§μΉ λΉνκΈ° λΈλλ°μ€μ²λΌ μ€λ₯κ° λ°μνκΈ°κΉμ§μ λͺ¨λ κ²½λ‘μ κ·Έ μκ°μ λ°μ΄ν°λ₯Ό κΈ°λ‘ν΄ μ€λλ€. νμ§λ§ κ°λ ₯ν νμλ ν° μ±
μμ΄ λ°λ₯΄λ λ²! νΉν diagnose μ΅μ
μ μμ²λ λ₯λ ₯κ³Ό κ·Έμ λ°λ₯Έ μ€μν 보μ κ²½κ³ μ λν΄ μ§μ€μ μΌλ‘ λ€λ€λ³΄κ² μ΅λλ€.
μ΄λ² μ±ν°λ₯Ό λ§μΉλ©΄ μ¬λ¬λΆμ λ€μμ ν μ μκ² λ κ±°μμ!
backtrace=True μ΅μ
μ μ¬μ©νμ¬ μ 체 νΈμΆ μ€ν(Full Stack Trace)μ μΆμ νκ³ μλ¬μ κ·Όλ³Έ μμΈμ νμ
ν μ μμ΅λλ€.diagnose=True μ΅μ
μ μ¬μ©νμ¬ μμΈ λ°μ μμ μ λ³μ κ°λ€κΉμ§ νμΈνλ κΆκ·Ήμ λλ²κΉ
μ ν μ μμ΅λλ€.diagnose=True μ΅μ
μ΄ νλ‘λμ
νκ²½μμ μ μ λ μ¬μ©λλ©΄ μ λλμ§, κ·Έ μ¬κ°ν 보μ μνμ λͺ
νν μ΄ν΄νκ³ μ€λͺ
ν μ μμ΅λλ€.deep_dive_debugging.py νμΌμ μλ‘ μΆκ°νμ¬ μ€μ΅ν©λλ€. μ΄ μ½λλ (1)κΈ°λ³Έ, (2)backtrace, (3)diagnose μΈ κ°μ§ μ΅μ
μΌλ‘ κ°κ° λ€λ₯Έ λ‘κ·Έ νμΌμ μμ±νμ¬, κ° μ΅μ
μ΄ μμΈ λ‘κ·Έλ₯Ό μ΄λ»κ² λ³νμν€λμ§ λͺ
ννκ² λΉκ΅ν©λλ€.
νλ‘μ νΈ κ΅¬μ‘°
loguru-course/
βββ venv/
βββ ... (μ΄μ κ°μ νμΌλ€)
βββ deep_dive_debugging.py <- μλ‘ μΆκ°λ νμΌ!
βββ debug_default.log <- μ€ν ν μμ±λ νμΌ 1
βββ debug_backtrace.log <- μ€ν ν μμ±λ νμΌ 2
βββ debug_diagnose.log <- μ€ν ν μμ±λ νμΌ 3
deep_dive_debugging.py μ 체 μ½λ
# deep_dive_debugging.py
import sys
from loguru import logger
# μ€μ μ κΈ°μ‘΄ νΈλ€λ¬ λͺ¨λ μ κ±°
logger.remove()
# --- μ€μ 1: κΈ°λ³Έ μμΈ λ‘κΉ
(μ§§μ νΈλ μ΄μ€, λ³μκ° νμ μ ν¨) ---
logger.add("debug_default.log", level="ERROR", backtrace=False, diagnose=False)
# --- μ€μ 2: backtrace=True ---
# μμΈκ° μ‘ν μ§μ μ λμ΄ μ 체 νΈμΆ κ²½λ‘λ₯Ό 보μ¬μ€λλ€.
logger.add("debug_backtrace.log", level="ERROR", backtrace=True, diagnose=False)
# --- μ€μ 3: diagnose=True ---
# μ€ν κ° νλ μμ λ³μ κ°κΉμ§ 보μ¬μ€λλ€. (π¨λ³΄μ μ£Όμπ¨)
# β» diagnoseλ backtraceμ λ
립 μ΅μ
μ΄λ―λ‘, ν¨κ» Trueλ‘ λμ΄ λΉκ΅λ₯Ό λͺ
νν ν©λλ€.
logger.add("debug_diagnose.log", level="ERROR", backtrace=True, diagnose=True)
def calculate_inverse(value, secret_key):
# μ΄ ν¨μ λ΄λΆμμ 'ZeroDivisionError' μμΈκ° λ°μν©λλ€.
logger.info(f"'{value}'μ μμλ₯Ό κ³μ°ν©λλ€. KEY: {secret_key}")
return 1 / value
def process_data(data, key):
# μ€κ° λ¨κ³μ ν¨μ. μ¬κΈ°μ μμΈλ₯Ό μ‘μμ λ‘κΉ
ν©λλ€.
try:
result = calculate_inverse(data, key)
print(f"κ³μ° κ²°κ³Ό: {result}")
except ZeroDivisionError:
# logger.exception()μ μμΈ μ 보λ₯Ό μλμΌλ‘ λ‘κ·Έμ ν¬ν¨μμΌμ€λλ€.
logger.exception("λ°μ΄ν° μ²λ¦¬ μ€ μμμΉ λͺ»ν μ€λ₯κ° λ°μνμ΅λλ€.")
def main():
api_key = "super-secret-api-key-12345"
process_data(10, api_key)
process_data(0, api_key) # μ΄ νΈμΆμμ μμΈκ° λ°μν©λλ€.
if __name__ == "__main__":
main()
print("\\nμ€μ΅ μλ£! νλ‘μ νΈ ν΄λμ μμ±λ 3κ°μ λ‘κ·Έ νμΌμ μ΄μ΄ λΉκ΅ν΄λ³΄μΈμ.")
backtrace=True: μ 체 νΈμΆ κ²½λ‘ μΆμ νκΈ°(μ΄λ² μ€μ΅μ κΈ°λ³Έ μ€μ μΈ backtrace=False, diagnose=Falseμμλ) μμΈκ° except λΈλ‘μμ μ‘ν λΆλΆ μ€μ¬μ λΉκ΅μ μ§§μ νΈλ μ΄μ€κ° μΆλ ₯λ©λλ€. λ°λ©΄ backtrace=Trueλ₯Ό μΌλ©΄, μμΈκ° λ°μν μ§μ μμλΆν° νλ‘κ·Έλ¨μ΄ μμλ μ§μ κΉμ§μ μ 체 ν¨μ νΈμΆ κ²½λ‘λ₯Ό μμΆμ νμ¬ λ³΄μ¬μ€λλ€.