---
title: "إعداد التسجيل في Python بمستويات السجل الصحيحة والتقاط الاستثناءات"
description: "لا يطبع logging في Python سوى WARNING وما فوقه حتى تضبطه. إليك الإعداد في 3 أسطر، ومستويات السجل الـ5، وكيف تسجّل استثناءً مع تتبّع المكدّس الخاص به، من اختبار على Python 3.13."
canonical: "https://logbrew.co/ar/guides/python-logging"
last_updated: "2026-11-10"
---

# إعداد التسجيل في Python بمستويات السجل الصحيحة والتقاط الاستثناءات

لا يطبع `logging` في Python سوى WARNING وما فوقه حتى تضبطه. إليك الإعداد في 3 أسطر، ومستويات السجل الـ5، وكيف تسجّل استثناءً مع تتبّع المكدّس الخاص به، من اختبار على Python 3.13.

اختُبر في 10 نوفمبر 2026 باستخدام Python 3.13.5 وlogbrew-sdk 0.1.29

بقلم [Furkan Erday](https://github.com/furkanerday). Furkan Erday مؤسس LogBrew، ويبني LogBrew كل يوم باستخدام Claude Code وCodex.

Canonical: https://logbrew.co/ar/guides/python-logging

## ما يفعله كل مستوى سجل في Python دون إعداد، وفي LogBrew

| استدعاء التسجيل | يُطبع دون إعداد | مستوى مستقل في LogBrew |
| --- | --- | --- |
| `log.debug()` | أُسقط | دُمج في `info` |
| `log.info()` | أُسقط | `info` |
| `log.warning()` | `WARNING:root:` | `warning` |
| `log.error()` | `ERROR:root:` | `error` |
| `log.critical()` | `CRITICAL:root:` | `critical` |

5 استدعاءات للمسجّل الجذري دون أي إعداد، ثم الاستدعاءات الـ5 نفسها عبر معالج LogBrew. الكوب الممتلئ يعني أن السطر طُبع، أو حُفظ كمستوى مستقل.

## أعدّ التسجيل في 3 أسطر

### استدعِ basicConfig() مرة واحدة قبل أول استدعاء للسجل

يضبط `basicConfig()` مستوى المسجّل الجذري وتنسيق السطر. دون إعداد، يطبع Python مستوى WARNING وما فوقه فقط، مثل `WARNING:root:keg below 10%`، ويُسقط DEBUG وINFO.

```bash
import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)s %(name)s %(message)s",
)
log = logging.getLogger("taproom")

log.debug("keg pressure read")
log.info("tap opened")
log.warning("keg below 10%")
log.error("keg empty")
log.critical("cooler offline")
```

المخرجات

```text
2026-11-10 08:34:04,828 INFO taproom tap opened
2026-11-10 08:34:04,828 WARNING taproom keg below 10%
2026-11-10 08:34:04,828 ERROR taproom keg empty
2026-11-10 08:34:04,828 CRITICAL taproom cooler offline
```

### سمِّ المسجّل باسم كل وحدة

يمنح `logging.getLogger(__name__)` كل وحدة مسجّلها الخاص، فيذكر كل سطر الوحدة التي جاء منها. استخدم المسجّل الجذري لـ`basicConfig()` فقط.

### اقرأ المستوى من متغير بيئة

يقبل `basicConfig()` اسم المستوى كنص. شغّل هذا مع `LOG_LEVEL=DEBUG` فتظهر أسطر التصحيح دون تغيير الكود.

```bash
import logging
import os

logging.basicConfig(level=os.environ.get("LOG_LEVEL", "INFO"))
log = logging.getLogger("taproom")
log.debug("keg pressure read")
log.info("tap opened")
```

المخرجات

```text
DEBUG:taproom:keg pressure read
INFO:taproom:tap opened
```

### مرّر force=True لإعادة الضبط

يتجاهل Python استدعاء `basicConfig()` الثاني عندما يكون للمسجّل الجذري معالج بالفعل. مرّر `force=True` لاستبدال المعالج، في الاختبارات مثلًا.

```bash
import logging

logging.basicConfig(level=logging.WARNING)
logging.basicConfig(level=logging.DEBUG)
logging.debug("second basicConfig: not printed")
logging.basicConfig(level=logging.DEBUG, force=True)
logging.debug("basicConfig with force=True: printed")
```

المخرجات

```text
DEBUG:root:basicConfig with force=True: printed
```

## سجّل كل استثناء مع تتبّع المكدّس الخاص به

### استدعِ log.exception() داخل except

يسجّل `log.exception()` بمستوى ERROR ويرفق تتبّع المكدّس. مرّر `exc_info=True` إلى استدعاء بأي مستوى آخر لفعل الشيء نفسه هناك.

```bash
import logging

logging.basicConfig(level=logging.INFO, format="%(levelname)s %(name)s %(message)s")
log = logging.getLogger("taproom")
taps = {"ipa": 12}

def pour(beer):
    return taps[beer]

try:
    pour("stout")
except KeyError:
    log.exception("pour failed")
```

المخرجات

```text
ERROR taproom pour failed
Traceback (most recent call last):
  File "app.py", line 11, in <module>
    pour("stout")
    ~~~~^^^^^^^^^
  File "app.py", line 8, in pour
    return taps[beer]
           ~~~~^^^^^^
KeyError: 'stout'
```

### أرسل كل سطر إلى LogBrew عبر معالج تسجيل

أضف `LogBrewLoggingHandler` إلى مسجّلك. يصبح كل record سجلًا في LogBrew بمستواه واسم مسجّله وملفه ورقم سطره. يُرسل معه اسم الاستثناء ورسالته، وكذلك القيم في `extra={}`.

```bash
import logging
import os

from logbrew_sdk import HttpTransport, LogBrewClient, LogBrewLoggingHandler

client = LogBrewClient.create(api_key=os.environ["LOGBREW_SERVER_API_KEY"])
transport = HttpTransport()
log = logging.getLogger("taproom")
log.addHandler(LogBrewLoggingHandler(client, transport, metadata={"service": "taproom"}))
log.setLevel(logging.INFO)

taps = {"ipa": 12}

def pour(beer):
    return taps[beer]

try:
    pour("stout")
except KeyError:
    log.exception("pour failed", extra={"order_id": "ord_42"})

response = client.flush(transport)
print("HTTP", response.status_code, "accepted", response.accepted_events, "logs")
```

المخرجات

```text
HTTP 200 accepted 1 logs
```

### اقرأ السجلات مجددًا مع حقول الاستثناء

يعيد `logbrew read logs --severity error --json` الأسطر مع `exceptionName` و`exceptionMessage` والملف والدالة ورقم السطر و`order_id` الخاص بك.

```bash
logbrew read logs --project <project_id> --severity error --since 1h --json | jq '.[0] | {level, message, logger: .attributes.logger, metadata: .attributes.metadata}'
```

المخرجات

```text
{
  "level": "error",
  "message": "pour failed",
  "logger": "taproom",
  "metadata": {
    "exceptionMessage": "'stout'",
    "exceptionName": "KeyError",
    "fileName": "send.py",
    "functionName": "<module>",
    "levelName": "ERROR",
    "levelNumber": 40,
    "lineNumber": 20,
    "module": "send",
    "order_id": "ord_42",
    "processName": "MainProcess",
    "service": "taproom",
    "threadName": "MainThread"
  }
}
```

### التقط الأعطال التي توقف العملية

يرتبط `install_process_error_capture()` بـ`sys.excepthook`. يصبح الاستثناء الذي لم يلتقطه أحد مشكلة بمستوى `critical` مع `handled: false`، وتُسجَّل قبل أن تخرج العملية بالرمز 1.

```bash
import atexit
import json
import os

from logbrew_sdk import LogBrewClient, RecordingTransport, install_process_error_capture

transport = RecordingTransport.always_accept()
client = LogBrewClient.create(api_key=os.environ["LOGBREW_SERVER_API_KEY"], transport=transport)
install_process_error_capture(client, on_capture_error=print)


@atexit.register
def show_captured_issue() -> None:
    issue = json.loads(transport.last_body())["events"][0]["attributes"]
    print(json.dumps({k: issue[k] for k in ("title", "level")}), json.dumps(issue["exception"]))


kegs = {"ipa": 3}
kegs["stout"] -= 1
```

المخرجات

```text
Traceback (most recent call last):
  File "<stdin>", line 19, in <module>
KeyError: 'stout'
{"title": "KeyError", "level": "critical"} {"type": "KeyError", "mechanism": {"type": "python.excepthook", "handled": false}}
```

## ما رأيناه في الاختبار

دون إعداد، طبعت 5 استدعاءات للمسجّل الجذري 3 أسطر إلى stderr وأُسقط استدعاءا DEBUG وINFO. السطر الافتراضي هو المستوى واسم المسجّل والرسالة، مثل `WARNING:root:keg below 10%`.

لم يغيّر استدعاء `basicConfig()` الثاني شيئًا حتى مرّرنا `force=True`. عبر معالج LogBrew، وصلت records مستوى DEBUG وINFO كمستوى `info`، وWARNING كـ`warning`، وERROR كـ`error`، وCRITICAL كـ`critical`.

أضاف `log.exception()` الحقلين `exceptionName` و`exceptionMessage` إلى سجل LogBrew. مع `include_exception_text=True` في المعالج، وصل تتبّع المكدّس كاملًا كـ`exceptionText`.

```bash
import logging

logging.debug("keg pressure read")
logging.info("tap opened")
logging.warning("keg below 10%")
logging.error("keg empty")
logging.critical("cooler offline")
```

المخرجات

```text
WARNING:root:keg below 10%
ERROR:root:keg empty
CRITICAL:root:cooler offline
```

## مستويات السجل الـ5 ومتى تستخدم كلًا منها

DEBUG للقيم التي تحتاجها أثناء إصلاح خطأ، مثل ضغط البرميل أو نص SQL أو عدد المحاولات. عطّله في الإنتاج.

يسجّل INFO ما فعله البرنامج، مثل فتح صنبور أو دفع طلب. يسجّل WARNING ما ساء لكن جرى التعامل معه، مثل برميل تحت 10%. يسجّل ERROR الطلبات أو المهام التي فشلت، مثل برميل فارغ. يسجّل CRITICAL ما أوقف البرنامج، مثل توقف المبرّد.

سجّل كل استثناء مرة واحدة، حيث تعالجه. سطر في كل مستوى من مكدّس الاستدعاء يرسل 3 تنبيهات لفشل واحد.

```bash
import logging

for name in ("DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"):
    print(name, logging.getLevelName(name))
print("root logger level:", logging.getLevelName(logging.getLogger().level))
```

المخرجات

```text
DEBUG 10
INFO 20
WARNING 30
ERROR 40
CRITICAL 50
root logger level: WARNING
```

## ما يسجّله LogBrew

يصبح كل record سجلًا واحدًا بمستواه واسم مسجّله واسم ملفه ودالته ورقم سطره ووحدته. تصبح القيم الأولية من `extra={}` حقولًا يمكنك فلترتها، ويضيف `metadata={}` في المعالج حقولًا إلى كل سطر، مثل `service` أعلاه.

عند وجود استثناء، يحصل السجل على `exceptionName` و`exceptionMessage`. مرّر `include_exception_text=True` إلى المعالج لحفظ نص تتبّع المكدّس أيضًا.

يحوّل `install_process_error_capture()` الاستثناء غير الملتقط إلى مشكلة بمستوى `critical`، مع نوع الاستثناء وإطارات المكدّس وآلية `python.excepthook`.

## أسئلة شائعة

### ما مستوى التسجيل الافتراضي في Python؟

WARNING. دون استدعاء `basicConfig()`، يطبع المسجّل الجذري WARNING وERROR وCRITICAL إلى stderr بالشكل `WARNING:root:message`، ويُسقط DEBUG وINFO.

### لماذا لا يفعل logging.basicConfig شيئًا؟

للمسجّل الجذري معالج بالفعل، من استدعاء `basicConfig()` سابق أو من مكتبة، لذا يتجاهل Python الاستدعاء. مرّر `force=True` لاستبدال المعالج.

### ما الفرق بين logging.error وlogging.exception؟

`log.exception()` هو `log.error()` مع `exc_info=True`. يسجّل بمستوى ERROR ويرفق تتبّع المكدّس. استدعه داخل كتلة `except` فقط.

### ما ترتيب مستويات التسجيل في Python؟

DEBUG 10، INFO 20، WARNING 30، ERROR 40، CRITICAL 50. يمرّر المسجّل record عندما يكون رقمه مساويًا للمستوى الذي ضبطته أو أعلى منه.

### هل أستخدم print() أم logging في Python؟

استخدم `logging`. لا يملك `print()` مستويات ولا طوابع زمنية ولا أسماء مسجّلات ولا معالجات. مع `logging` تفعّل الأسطر لكل وحدة وترسلها إلى ملف أو إلى LogBrew.

## اطّلع على كل استثناء Python مع تتبّع المكدّس الخاص به

ترسل SDK LogBrew لـPython كل سطر سجل بمستواه ومسجّله وملفه وسطره، وتحوّل الاستثناءات غير الملتقطة إلى مشكلات مع تتبّع المكدّس. ابدأ بخطة مجانية سخية دون بطاقة.

[ابدأ مجانًا](https://logbrew.co/ar)

## المصادر

- [Python docs, Logging HOWTO](https://docs.python.org/3/howto/logging.html)
- [Python docs, logging module](https://docs.python.org/3/library/logging.html)
- [python/cpython#78078](https://github.com/python/cpython/issues/78078)

## أدلة أخرى للوكلاء وPython

- [أضف خادم MCP إلى Claude Code وCodex](https://logbrew.co/ar/guides/mcp-server-claude-code-codex)
- [استخدم AGENTS.md في Claude Code وCodex](https://logbrew.co/ar/guides/agents-md)
- [أصلح خطأ Claude overloaded 529 وخطأ rate limit 429](https://logbrew.co/ar/guides/claude-overloaded-rate-limit-error)
- [التسجيل المنظّم بتنسيق سجل ومستويات سجل يمكنك البحث فيها حسب الحقل](https://logbrew.co/ar/guides/structured-logging)
- [كيف تصلح الأخطاء في Claude Code وCodex وJavaScript وPython](https://logbrew.co/ar/guides)
