logging — level, handler, formatter, haqiqiy loyihada qanday ishlatiladi

~20 daq · Python · Ilg'or mavzular

Muammodan boshlaylik

Telegram bot serverda ishlayapti. Kechasi foydalanuvchi yozdi: "Bot javob bermayapti". Siz kodga print lar qo'shgansiz:

print("bu yerga keldi")
print(user)
print("xato bo'ldi")

Muammolar:

  • Server da print hech qayerga yozilmagan — terminal yopiq edi
  • Qaysi vaqtda bo'lgani noma'lum
  • Qaysi xabar muhim (xato), qaysisi — oddiy (debug) — farqi yo'q
  • Production da debug xabarlarini o'chirish uchun — har bir print ni qo'lda olib tashlash

logging nima?

logging — standart kutubxonadagi log yozish tizimi:

  • Har bir xabarda vaqt, daraja, modul
  • Darajalar — muhimligiga qarab filtrlash
  • Bir vaqtda konsolga, faylga, tashqi xizmatga yozish
  • Kodni o'zgartirmasdan — sozlama bilan boshqarish

Hayotiy o'xshatma

Kema jurnali. Kapitan har bir muhim hodisani vaqti bilan yozadi: "06:00 — portdan chiqdik" (INFO), "11:30 — shamol kuchaydi" (WARNING), "14:15 — dvigatel to'xtadi" (ERROR). Tekshiruvchi faqat jiddiy hodisalarni ko'rmoqchi bo'lsa — WARNING dan yuqorisini o'qiydi. Jurnal kema cho'kkan taqdirda ham saqlanib qoladi (faylga yozilgan).


Darajalar

Daraja Qiymat Qachon
DEBUG 10 Dasturchi uchun tafsilotlar: o'zgaruvchilar qiymati
INFO 20 Oddiy hodisalar: "server ishga tushdi", "buyurtma yaratildi"
WARNING 30 G'alati, lekin ishlayapti: "API sekin javob berdi"
ERROR 40 Xato — amal bajarilmadi
CRITICAL 50 Dastur ishlay olmaydi

Belgilangan darajadan past xabarlar e'tiborsiz qoldiriladi. Standart daraja — WARNING.


Tez boshlash — basicConfig

import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)-8s %(name)s: %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)

logging.debug("Bu ko'rinmaydi — DEBUG < INFO")
logging.info("Bot ishga tushdi")
logging.warning("API javobi 3 soniya kechikdi")
logging.error("Buyurtmani saqlab bo'lmadi")
2026-11-08 10:00:00 INFO     root: Bot ishga tushdi
2026-11-08 10:00:01 WARNING  root: API javobi 3 soniya kechikdi
2026-11-08 10:00:02 ERROR    root: Buyurtmani saqlab bo'lmadi

basicConfig — dasturning eng boshida, bir marta.


Har bir modulga o'z logger i

# dokon/tolov.py
import logging

logger = logging.getLogger(__name__)      # "dokon.tolov"

def tolash(buyurtma_id, summa):
    logger.info("To'lov boshlandi: buyurtma=%s summa=%s", buyurtma_id, summa)
    try:
        natija = provayder_api(summa)
    except ConnectionError:
        logger.exception("To'lov provayderiga ulanib bo'lmadi: buyurtma=%s", buyurtma_id)
        raise
    logger.info("To'lov muvaffaqiyatli: buyurtma=%s", buyurtma_id)
    return natija
  • logging.getLogger(__name__) — modul nomi bilan logger: logda xabar qaysi fayldan kelgani ko'rinadi
  • Modullarda logging.info(...) (root logger) emas — o'z logger ingiz

Parametrlar — %s bilan

logger.info("Foydalanuvchi %s kirdi", user_id)          # ✅
logger.info(f"Foydalanuvchi {user_id} kirdi")           # ishlaydi, lekin

%s uslubida satr faqat xabar haqiqatan yozilganda formatlanadi. logger.debug(f"... {ogir_hisob()}") — DEBUG o'chiq bo'lsa ham f-string hisoblanadi.

logger.exception — traceback bilan

try:
    1 / 0
except ZeroDivisionError:
    logger.exception("Hisoblashda xato")     # ERROR darajasi + to'liq traceback

except blokida xatoni log qilishning eng yaxshi usuli — sabab va qator raqami saqlanadi (31-dars).


Handler va Formatter

Log tizimi uch qismdan iborat:

Logger ──xabar──▶ Handler(lar) ──▶ qayerga: konsol, fayl, email, tashqi xizmat
                     │
                  Formatter — qanday ko'rinishda
import logging
from logging.handlers import RotatingFileHandler

logger = logging.getLogger("bot")
logger.setLevel(logging.DEBUG)

formatter = logging.Formatter(
    "%(asctime)s %(levelname)s [%(name)s:%(lineno)d] %(message)s"
)

# konsolga — INFO va yuqori
konsol = logging.StreamHandler()
konsol.setLevel(logging.INFO)
konsol.setFormatter(formatter)

# faylga — hammasi, 5 MB dan oshsa yangi fayl, 3 ta eski fayl saqlanadi
fayl = RotatingFileHandler("bot.log", maxBytes=5_000_000, backupCount=3, encoding="utf-8")
fayl.setLevel(logging.DEBUG)
fayl.setFormatter(formatter)

logger.addHandler(konsol)
logger.addHandler(fayl)
Handler Qayerga
StreamHandler Konsol (stderr)
FileHandler Fayl
RotatingFileHandler Fayl, hajm bo'yicha aylantiriladi
TimedRotatingFileHandler Fayl, vaqt bo'yicha (har kuni)
SMTPHandler Email

[!TIP] Oddiy FileHandler bilan log fayli oylar davomida o'sib, diskni to'ldirishi mumkin. Har doim RotatingFileHandler yoki TimedRotatingFileHandler ishlating. Docker va zamonaviy serverlarda esa ko'pincha faylga emas, stdout ga yoziladi — loglarni platforma yig'adi.

Format maydonlari

Maydon Ma'nosi
%(asctime)s Vaqt
%(levelname)s Daraja
%(name)s Logger nomi (modul)
%(message)s Xabar
%(filename)s, %(lineno)d Fayl va qator
%(funcName)s Funksiya

Haqiqiy loyihada — dictConfig

Sozlamani bitta joyda, kod sifatida:

# loyiha/log_sozlama.py
import logging.config
import os

def sozla():
    logging.config.dictConfig({
        "version": 1,
        "disable_existing_loggers": False,
        "formatters": {
            "oddiy": {"format": "%(asctime)s %(levelname)s %(name)s: %(message)s"},
        },
        "handlers": {
            "konsol": {"class": "logging.StreamHandler", "formatter": "oddiy"},
            "fayl": {
                "class": "logging.handlers.RotatingFileHandler",
                "filename": "app.log",
                "maxBytes": 5_000_000,
                "backupCount": 5,
                "encoding": "utf-8",
                "formatter": "oddiy",
            },
        },
        "root": {
            "level": os.getenv("LOG_LEVEL", "INFO"),
            "handlers": ["konsol", "fayl"],
        },
        "loggers": {
            "urllib3": {"level": "WARNING"},      # shovqinli kutubxonani jim qilish
        },
    })
# main.py
from loyiha.log_sozlama import sozla
import logging

def main():
    sozla()
    logging.getLogger(__name__).info("Ilova ishga tushdi")

if __name__ == "__main__":
    main()
  • Sozlash — faqat kirish nuqtasida (main), modullarda — faqat getLogger(__name__)
  • Daraja — muhit o'zgaruvchisidan: development da DEBUG, production da INFO

Nimani log qilish va nimani qilmaslik

✅ Log qiling:

  • Ilova ishga tushishi va to'xtashi
  • Muhim biznes hodisalar: buyurtma, to'lov, ro'yxatdan o'tish (ID lar bilan)
  • Tashqi xizmatlarga so'rovlar xatolari va sekin javoblar
  • Barcha kutilmagan xatolar — logger.exception

❌ Log qilmang:

  • Parollar, tokenlar, karta raqamlari, to'liq shaxsiy ma'lumotlar
  • Har bir sikl iteratsiyasi (INFO darajasida) — log fayli keraksiz ma'lumotga to'ladi

[!WARNING] Loglar ko'p odam va tizimlarga ko'rinadi va uzoq saqlanadi. logger.info("Kirish: %s", request_data) — agar request_data da parol bo'lsa, u log faylida ochiq qoladi. Faqat kerakli, maxfiy bo'lmagan maydonlarni yozing.


Tez-tez uchraydigan xatolar

Hech narsa chiqmaydi:

logging.info("Salom")     # ❌ ko'rinmaydi — standart daraja WARNING

basicConfig(level=logging.INFO).

basicConfig ni kech chaqirish — undan oldin biror log yozilgan bo'lsa, basicConfig ishlamaydi. Dastur boshida.

Handler ni har chaqiruvda qo'shish:

def ol_logger():
    logger = logging.getLogger("app")
    logger.addHandler(logging.StreamHandler())   # ❌ har chaqiruvda yana bitta — xabarlar ko'payadi
    return logger

Sozlash — bir marta.

except da logger.error(e) — traceback yo'qoladi; logger.exception(...).


Xulosa

logging — vaqt, daraja va manba bilan boshqariladigan log yozish tizimi.

Eslab qoling:

  • Darajalar: DEBUG < INFO < WARNING < ERROR < CRITICAL; standart — WARNING
  • basicConfig(level=..., format=...) — boshida, bir marta
  • Har modulda — logger = logging.getLogger(__name__)
  • logger.info("... %s", x); xatolar — logger.exception(...) (traceback bilan)
  • Handler — qayerga (konsol, aylantiriladigan fayl); Formatter — qanday
  • Loyihada — dictConfig, daraja muhit o'zgaruvchisidan
  • Maxfiy ma'lumotlarni log qilmang

Kurs yakunlandi

Tabriklaymiz — Python kursini tugatdingiz! Siz o'zgaruvchilar va sikllardan boshlab ma'lumot turlari, funksiyalar, dekoratorlar, OOP, xatolar va fayllar, standart kutubxona va ilg'or mavzular — generatorlar, type hints, dataclasses va logging gacha bo'lgan yo'lni bosib o'tdingiz.

Keyingi qadamlar:

  • O'z loyihangizni yarating: Telegram bot, fayllarni saralovchi skript, hisobot generatori
  • Web dasturlash — Django yoki FastAPI
  • Ma'lumotlar tahlili — pandas, numpy
  • Ma'lumotlar bazasi — PostgreSQL yoki MySQL kurslari