بايثون بالمثال 19: إنشاء برنامج دفتر جهات اتصال وحفظ البيانات في JSON

إنشاء برنامج دفتر جهات اتصال ببايثون وحفظ البيانات في JSON

بعد أن تتعلم القوائم والقواميس والدوال والملفات في بايثون، تحتاج إلى مشروع صغير يجمع هذه المهارات داخل برنامج واحد مفيد. من الأمثلة المناسبة للمبتدئ برنامج دفتر جهات اتصال تستطيع من خلاله إضافة الأسماء وأرقام الهواتف، وعرض البيانات، والبحث عن شخص، وتعديل معلوماته أو حذفها.

لكن تخزين جهات الاتصال داخل قائمة عادية لا يكفي؛ لأن البيانات ستختفي بمجرد إغلاق البرنامج. لذلك سنطوّر المثال تدريجيًا حتى نحفظ جميع جهات الاتصال داخل ملف JSON، ثم نقرأها تلقائيًا في المرة التالية التي نشغّل فيها البرنامج.

في هذا المقال من سلسلة بايثون بالمثال ستبني برنامجًا كاملًا يعمل من سطر الأوامر، وستتعلم كيف تنظّم البيانات داخل قائمة من القواميس، وتتحقق من المدخلات، وتقسم البرنامج إلى دوال واضحة، وتحفظ البيانات بطريقة تجعلها باقية بعد إغلاق البرنامج.

{alertInfo} الفكرة ببساطة: سنخزن كل جهة اتصال داخل Dictionary يحتوي على الاسم ورقم الهاتف والبريد، ثم نضع جميع القواميس داخل List. بعد كل إضافة أو تعديل أو حذف، نحفظ القائمة داخل ملف contacts.json.

{getToc} $title={محتوى المقال}

ماذا سنبني في هذا المثال؟

سننشئ برنامج دفتر جهات اتصال يوفر الخيارات التالية:

  • إضافة جهة اتصال جديدة.
  • عرض جميع جهات الاتصال.
  • البحث عن جهة اتصال بالاسم.
  • تعديل رقم الهاتف أو البريد الإلكتروني.
  • حذف جهة اتصال بعد التأكيد.
  • حفظ البيانات تلقائيًا داخل ملف JSON.
  • تحميل البيانات السابقة عند تشغيل البرنامج.
  • التعامل مع ملف مفقود أو فارغ أو غير صالح.

سيعمل البرنامج من خلال قائمة نصية تظهر في Terminal أو CMD، ويختار المستخدم العملية بكتابة رقم من 1 إلى 6.

المهارات التي ستتدرب عليها

المهارةكيف سنستخدمها؟
Listتخزين جميع جهات الاتصال داخل قائمة واحدة.
Dictionaryتخزين الاسم ورقم الهاتف والبريد لكل شخص.
الدوالتقسيم الإضافة والبحث والحذف والحفظ إلى وظائف مستقلة.
if وwhileالتحقق من المدخلات وتشغيل القائمة الرئيسية باستمرار.
ملفات JSONحفظ البيانات وقراءتها بين مرات تشغيل البرنامج.
try وexceptمنع توقف البرنامج عند وجود مشكلة في ملف البيانات.
pathlibتحديد مسار ملف جهات الاتصال بطريقة واضحة.

هيكل ملفات المشروع

أنشئ مجلدًا جديدًا باسم contact_book، ثم أنشئ داخله ملف Python باسم contact_book.py.

contact_book/
│
├── contact_book.py
└── contacts.json

لا تحتاج إلى إنشاء ملف contacts.json يدويًا. سيقوم البرنامج بإنشائه عند حفظ أول جهة اتصال. وضعناه في المخطط فقط حتى تفهم شكل المشروع بعد تشغيله.

كيف سننظم بيانات جهات الاتصال؟

كل جهة اتصال تحتوي على أكثر من معلومة، لذلك القاموس Dictionary مناسب لتمثيلها.

contact = {
    "name": "Ali",
    "phone": "+967 777 123 456",
    "email": "ali@example.com"
}

المفاتيح في القاموس هي name للاسم، وphone لرقم الهاتف، وemail للبريد الإلكتروني.

ولأن البرنامج سيحتوي على أكثر من جهة اتصال، سنضع القواميس داخل قائمة:

contacts = [
    {
        "name": "Ali",
        "phone": "+967 777 123 456",
        "email": "ali@example.com"
    },
    {
        "name": "Sara",
        "phone": "+967 733 987 654",
        "email": "sara@example.com"
    }
]

بهذا التنظيم يمكنك المرور على جميع جهات الاتصال باستخدام حلقة، أو البحث داخلها، أو تحويلها بسهولة إلى ملف JSON.

تنظيم بيانات جهات الاتصال باستخدام قائمة من القواميس في بايثون

النسخة الأولى: إضافة جهة اتصال إلى قائمة

سنبدأ بنسخة بسيطة لا تحفظ البيانات في ملف بعد. أنشئ قائمة فارغة، ثم اطلب من المستخدم إدخال البيانات.

contacts = []

name = input("أدخل الاسم: ").strip()
phone = input("أدخل رقم الهاتف: ").strip()
email = input("أدخل البريد الإلكتروني: ").strip()

contact = {
    "name": name,
    "phone": phone,
    "email": email
}

contacts.append(contact)
print(contacts)

استخدمنا strip() لإزالة المسافات الزائدة من بداية ونهاية الإدخال، ثم أنشأنا قاموسًا وأضفناه إلى القائمة باستخدام append().

تحويل الإضافة إلى دالة مستقلة

من الأفضل وضع منطق الإضافة داخل دالة، حتى نستطيع استدعاءه من القائمة الرئيسية كلما اختار المستخدم إضافة جهة اتصال.

def add_contact(contacts):
    name = input("أدخل الاسم: ").strip()
    phone = input("أدخل رقم الهاتف: ").strip()
    email = input("أدخل البريد الإلكتروني: ").strip()

    contact = {
        "name": name,
        "phone": phone,
        "email": email
    }

    contacts.append(contact)
    print("تمت إضافة جهة الاتصال بنجاح.")

الدالة تستقبل القائمة نفسها، ثم تضيف القاموس الجديد إليها. لأن القائمة قابلة للتعديل، ستبقى جهة الاتصال مضافة بعد انتهاء الدالة.

التحقق من الاسم ورقم الهاتف

لا نريد قبول اسم فارغ أو رقم هاتف مكوّن من حروف. نبدأ بدالة تتحقق من رقم الهاتف بعد إزالة المسافات والشرطات وعلامة + في البداية.

def is_valid_phone(phone):
    cleaned_phone = phone.replace(" ", "").replace("-", "")

    if cleaned_phone.startswith("+"):
        cleaned_phone = cleaned_phone[1:]

    return cleaned_phone.isdigit() and len(cleaned_phone) >= 7

هذا تحقق مبسط للتدريب، وليس نظامًا عالميًا لجميع أرقام الهواتف؛ لأن أطوال وصيغ الأرقام تختلف بين الدول.

التحقق من البريد الإلكتروني

سنجعل البريد اختياريًا. إذا تركه المستخدم فارغًا نقبله، وإذا كتب قيمة نتحقق بصورة مبسطة من وجود @ ونقطة داخل اسم النطاق.

def is_valid_email(email):
    if not email:
        return True

    if "@" not in email:
        return False

    domain = email.split("@", 1)[1]
    return "." in domain

منع تكرار جهة الاتصال بالاسم

ننشئ دالة تبحث عن الاسم وتعيد موقعه داخل القائمة. نستخدم casefold() حتى لا يجعل اختلاف الحروف الكبيرة والصغيرة الاسم يبدو جديدًا.

def find_contact_index(contacts, name):
    normalized_name = name.casefold()

    for index, contact in enumerate(contacts):
        if contact["name"].casefold() == normalized_name:
            return index

    return None

دالة الإضافة بعد التحقق من البيانات

def add_contact(contacts):
    name = input("أدخل الاسم: ").strip()

    if not name:
        print("الاسم لا يمكن أن يكون فارغًا.")
        return

    if find_contact_index(contacts, name) is not None:
        print("توجد جهة اتصال بهذا الاسم مسبقًا.")
        return

    phone = input("أدخل رقم الهاتف: ").strip()

    if not is_valid_phone(phone):
        print("رقم الهاتف غير صالح.")
        return

    email = input(
        "أدخل البريد الإلكتروني أو اتركه فارغًا: "
    ).strip()

    if not is_valid_email(email):
        print("البريد الإلكتروني غير صالح.")
        return

    contacts.append({
        "name": name,
        "phone": phone,
        "email": email
    })

    print("تمت إضافة جهة الاتصال بنجاح.")
إضافة جهة اتصال والتحقق من الاسم ورقم الهاتف في بايثون

عرض جميع جهات الاتصال

نستخدم حلقة for مع enumerate() لعرض كل جهة اتصال برقم متسلسل.

def list_contacts(contacts):
    if not contacts:
        print("لا توجد جهات اتصال محفوظة.")
        return

    print("\n--- جهات الاتصال ---")

    for number, contact in enumerate(contacts, start=1):
        email = contact["email"] or "غير مضاف"

        print(f"\n{number}. الاسم: {contact['name']}")
        print(f"   الهاتف: {contact['phone']}")
        print(f"   البريد: {email}")

البحث عن جهة اتصال بالاسم

سنسمح بالبحث باستخدام جزء من الاسم، وليس الاسم كاملًا فقط. نستخدم قائمة مشتقة لجمع النتائج، ثم نعيد استخدام دالة العرض.

def search_contacts(contacts):
    query = input("أدخل الاسم أو جزءًا منه: ").strip()

    if not query:
        print("اكتب اسمًا للبحث.")
        return

    normalized_query = query.casefold()

    matches = [
        contact
        for contact in contacts
        if normalized_query in contact["name"].casefold()
    ]

    if not matches:
        print("لم يتم العثور على جهة اتصال مطابقة.")
        return

    list_contacts(matches)

تعديل جهة اتصال موجودة

نطلب الاسم الكامل، ثم نصل إلى القاموس المطلوب. إذا ضغط المستخدم Enter دون كتابة قيمة جديدة، نحتفظ بالقيمة الحالية.

def update_contact(contacts):
    name = input("أدخل الاسم الكامل لجهة الاتصال: ").strip()
    index = find_contact_index(contacts, name)

    if index is None:
        print("جهة الاتصال غير موجودة.")
        return

    contact = contacts[index]

    new_phone = input(
        f"رقم الهاتف الجديد [{contact['phone']}]: "
    ).strip()

    new_email = input(
        f"البريد الجديد [{contact['email'] or 'غير مضاف'}]: "
    ).strip()

    if new_phone:
        if not is_valid_phone(new_phone):
            print("رقم الهاتف الجديد غير صالح.")
            return
        contact["phone"] = new_phone

    if new_email:
        if not is_valid_email(new_email):
            print("البريد الإلكتروني الجديد غير صالح.")
            return
        contact["email"] = new_email

    print("تم تعديل جهة الاتصال بنجاح.")
{alertInfo} في هذه النسخة، ترك البريد فارغًا أثناء التعديل يعني الاحتفاظ بالبريد الحالي، وليس حذفه. يمكنك لاحقًا إضافة خيار مستقل لمسح البريد.

حذف جهة اتصال بعد التأكيد

def delete_contact(contacts):
    name = input("أدخل الاسم الكامل لجهة الاتصال: ").strip()
    index = find_contact_index(contacts, name)

    if index is None:
        print("جهة الاتصال غير موجودة.")
        return

    contact = contacts[index]
    confirmation = input(
        f"هل تريد حذف {contact['name']}؟ (y/n): "
    ).strip().lower()

    if confirmation == "y":
        contacts.pop(index)
        print("تم حذف جهة الاتصال.")
    else:
        print("تم إلغاء الحذف.")
البحث عن جهة اتصال وتعديلها وحذفها باستخدام بايثون

لماذا تختفي البيانات عند إغلاق البرنامج؟

حتى الآن تُحفظ البيانات داخل الذاكرة فقط. عندما ينتهي تشغيل البرنامج، تختفي القائمة وجميع القواميس الموجودة فيها.

لحل المشكلة نستخدم ملف JSON، لأنه مناسب للقوائم والقواميس، وسهل القراءة، ومكتبته مدمجة مع بايثون.

تحديد مسار ملف البيانات باستخدام pathlib

from pathlib import Path

DATA_FILE = Path("contacts.json")

حفظ جهات الاتصال باستخدام json.dump

import json


def save_contacts(contacts):
    try:
        with DATA_FILE.open("w", encoding="utf-8") as file:
            json.dump(
                contacts,
                file,
                ensure_ascii=False,
                indent=4
            )
    except OSError as error:
        print(f"تعذر حفظ البيانات: {error}")

يضمن encoding="utf-8" دعم النص العربي، ويجعل ensure_ascii=False العربية ظاهرة طبيعيًا، بينما ينظم indent=4 الملف.

قد يصبح محتوى الملف بعد إضافة جهتي اتصال بهذا الشكل:

[
    {
        "name": "Ali",
        "phone": "+967 777 123 456",
        "email": "ali@example.com"
    },
    {
        "name": "Sara",
        "phone": "+967 733 987 654",
        "email": ""
    }
]

قراءة جهات الاتصال عند تشغيل البرنامج

إذا لم يكن الملف موجودًا نعيد قائمة فارغة. وإذا كان فارغًا أو تالفًا، نعالج JSONDecodeError بدل توقف البرنامج.

def load_contacts():
    if not DATA_FILE.exists():
        return []

    try:
        with DATA_FILE.open("r", encoding="utf-8") as file:
            contacts = json.load(file)

        if not isinstance(contacts, list):
            print("ملف البيانات لا يحتوي على قائمة صالحة.")
            return []

        return contacts

    except json.JSONDecodeError:
        print("ملف contacts.json فارغ أو غير صالح.")
        return []

    except OSError as error:
        print(f"تعذر قراءة البيانات: {error}")
        return []
حفظ جهات الاتصال في ملف JSON وقراءتها عند تشغيل برنامج بايثون

متى نحفظ البيانات؟

سنحفظ مباشرة بعد كل إضافة أو تعديل أو حذف، حتى لا تضيع التغييرات إذا أُغلقت النافذة فجأة.

# بعد الإضافة
contacts.append(contact)
save_contacts(contacts)

# بعد التعديل
contact["phone"] = new_phone
save_contacts(contacts)

# بعد الحذف
contacts.pop(index)
save_contacts(contacts)

إنشاء القائمة الرئيسية

def show_menu():
    print("\n=== دفتر جهات الاتصال ===")
    print("1. إضافة جهة اتصال")
    print("2. عرض جميع جهات الاتصال")
    print("3. البحث عن جهة اتصال")
    print("4. تعديل جهة اتصال")
    print("5. حذف جهة اتصال")
    print("6. خروج")

تشغيل البرنامج داخل حلقة while

def main():
    contacts = load_contacts()

    while True:
        show_menu()
        choice = input("اختر رقم العملية: ").strip()

        if choice == "1":
            add_contact(contacts)
        elif choice == "2":
            list_contacts(contacts)
        elif choice == "3":
            search_contacts(contacts)
        elif choice == "4":
            update_contact(contacts)
        elif choice == "5":
            delete_contact(contacts)
        elif choice == "6":
            print("تم إغلاق دفتر جهات الاتصال.")
            break
        else:
            print("الخيار غير صحيح. اختر رقمًا من 1 إلى 6.")

تشغيل main بالطريقة الصحيحة

if __name__ == "__main__":
    main()

الكود الكامل لبرنامج دفتر جهات الاتصال

ضع الكود التالي كاملًا داخل ملف contact_book.py:

import json
from pathlib import Path

DATA_FILE = Path("contacts.json")


def load_contacts():
    if not DATA_FILE.exists():
        return []

    try:
        with DATA_FILE.open("r", encoding="utf-8") as file:
            contacts = json.load(file)

        if not isinstance(contacts, list):
            print("ملف البيانات لا يحتوي على قائمة صالحة.")
            return []

        return contacts
    except json.JSONDecodeError:
        print("ملف contacts.json فارغ أو غير صالح.")
        return []
    except OSError as error:
        print(f"تعذر قراءة البيانات: {error}")
        return []


def save_contacts(contacts):
    try:
        with DATA_FILE.open("w", encoding="utf-8") as file:
            json.dump(
                contacts,
                file,
                ensure_ascii=False,
                indent=4
            )
    except OSError as error:
        print(f"تعذر حفظ البيانات: {error}")


def is_valid_phone(phone):
    cleaned_phone = phone.replace(" ", "").replace("-", "")
    if cleaned_phone.startswith("+"):
        cleaned_phone = cleaned_phone[1:]
    return cleaned_phone.isdigit() and len(cleaned_phone) >= 7


def is_valid_email(email):
    if not email:
        return True
    if "@" not in email:
        return False
    domain = email.split("@", 1)[1]
    return "." in domain


def find_contact_index(contacts, name):
    normalized_name = name.casefold()
    for index, contact in enumerate(contacts):
        if contact["name"].casefold() == normalized_name:
            return index
    return None


def add_contact(contacts):
    name = input("أدخل الاسم: ").strip()
    if not name:
        print("الاسم لا يمكن أن يكون فارغًا.")
        return

    if find_contact_index(contacts, name) is not None:
        print("توجد جهة اتصال بهذا الاسم مسبقًا.")
        return

    phone = input("أدخل رقم الهاتف: ").strip()
    if not is_valid_phone(phone):
        print("رقم الهاتف غير صالح.")
        return

    email = input(
        "أدخل البريد الإلكتروني أو اتركه فارغًا: "
    ).strip()
    if not is_valid_email(email):
        print("البريد الإلكتروني غير صالح.")
        return

    contacts.append({
        "name": name,
        "phone": phone,
        "email": email
    })
    save_contacts(contacts)
    print("تمت إضافة جهة الاتصال بنجاح.")


def list_contacts(contacts):
    if not contacts:
        print("لا توجد جهات اتصال محفوظة.")
        return

    print("\n--- جهات الاتصال ---")
    for number, contact in enumerate(contacts, start=1):
        email = contact["email"] or "غير مضاف"
        print(f"\n{number}. الاسم: {contact['name']}")
        print(f"   الهاتف: {contact['phone']}")
        print(f"   البريد: {email}")


def search_contacts(contacts):
    query = input("أدخل الاسم أو جزءًا منه: ").strip()
    if not query:
        print("اكتب اسمًا للبحث.")
        return

    normalized_query = query.casefold()
    matches = [
        contact
        for contact in contacts
        if normalized_query in contact["name"].casefold()
    ]

    if not matches:
        print("لم يتم العثور على جهة اتصال مطابقة.")
        return

    list_contacts(matches)


def update_contact(contacts):
    name = input("أدخل الاسم الكامل لجهة الاتصال: ").strip()
    index = find_contact_index(contacts, name)
    if index is None:
        print("جهة الاتصال غير موجودة.")
        return

    contact = contacts[index]
    new_phone = input(
        f"رقم الهاتف الجديد [{contact['phone']}]: "
    ).strip()
    new_email = input(
        f"البريد الجديد [{contact['email'] or 'غير مضاف'}]: "
    ).strip()

    if new_phone:
        if not is_valid_phone(new_phone):
            print("رقم الهاتف الجديد غير صالح.")
            return
        contact["phone"] = new_phone

    if new_email:
        if not is_valid_email(new_email):
            print("البريد الإلكتروني الجديد غير صالح.")
            return
        contact["email"] = new_email

    save_contacts(contacts)
    print("تم تعديل جهة الاتصال بنجاح.")


def delete_contact(contacts):
    name = input("أدخل الاسم الكامل لجهة الاتصال: ").strip()
    index = find_contact_index(contacts, name)
    if index is None:
        print("جهة الاتصال غير موجودة.")
        return

    contact = contacts[index]
    confirmation = input(
        f"هل تريد حذف {contact['name']}؟ (y/n): "
    ).strip().lower()

    if confirmation == "y":
        contacts.pop(index)
        save_contacts(contacts)
        print("تم حذف جهة الاتصال.")
    else:
        print("تم إلغاء الحذف.")


def show_menu():
    print("\n=== دفتر جهات الاتصال ===")
    print("1. إضافة جهة اتصال")
    print("2. عرض جميع جهات الاتصال")
    print("3. البحث عن جهة اتصال")
    print("4. تعديل جهة اتصال")
    print("5. حذف جهة اتصال")
    print("6. خروج")


def main():
    contacts = load_contacts()

    while True:
        show_menu()
        choice = input("اختر رقم العملية: ").strip()

        if choice == "1":
            add_contact(contacts)
        elif choice == "2":
            list_contacts(contacts)
        elif choice == "3":
            search_contacts(contacts)
        elif choice == "4":
            update_contact(contacts)
        elif choice == "5":
            delete_contact(contacts)
        elif choice == "6":
            print("تم إغلاق دفتر جهات الاتصال.")
            break
        else:
            print("الخيار غير صحيح. اختر رقمًا من 1 إلى 6.")


if __name__ == "__main__":
    main()

طريقة تشغيل البرنامج

افتح Terminal داخل مجلد المشروع، ثم شغّل الملف.

py contact_book.py

أو:

python contact_book.py

في macOS أو Linux قد تستخدم:

python3 contact_book.py

مثال تشغيل

=== دفتر جهات الاتصال ===
1. إضافة جهة اتصال
2. عرض جميع جهات الاتصال
3. البحث عن جهة اتصال
4. تعديل جهة اتصال
5. حذف جهة اتصال
6. خروج
اختر رقم العملية: 1

أدخل الاسم: Ali
أدخل رقم الهاتف: +967 777 123 456
أدخل البريد الإلكتروني أو اتركه فارغًا: ali@example.com
تمت إضافة جهة الاتصال بنجاح.

بعد الإضافة سيظهر ملف contacts.json داخل مجلد المشروع. أغلق البرنامج وشغّله مرة أخرى، ثم اختر عرض جهات الاتصال؛ ستجد أن البيانات ما زالت موجودة.

كيف يعمل البرنامج خطوة بخطوة؟

  1. يبدأ التنفيذ من الشرط if __name__ == "__main__".
  2. تستدعي main() الدالة load_contacts().
  3. تُقرأ البيانات القديمة من ملف JSON أو تبدأ قائمة فارغة.
  4. تعرض حلقة while القائمة الرئيسية.
  5. يُنفذ الخيار الذي يحدده المستخدم.
  6. بعد الإضافة أو التعديل أو الحذف تُحفظ القائمة مباشرة.
  7. تتكرر القائمة حتى يختار المستخدم الخروج.

أخطاء شائعة عند بناء دفتر جهات الاتصال

1. إعادة إنشاء القائمة داخل كل دورة

لا تكتب contacts = [] داخل حلقة القائمة؛ لأن ذلك يمسح البيانات في كل دورة. حمّل القائمة مرة واحدة قبل الحلقة.

2. نسيان الحفظ بعد التعديل

تعديل القاموس في الذاكرة لا يكفي. استدعِ save_contacts() بعد الإضافة والتعديل والحذف.

3. الخلط بين dump وdumps

json.dump() تكتب داخل ملف، بينما json.dumps() تعيد نص JSON داخل البرنامج.

4. نسيان ensure_ascii=False

استخدمه مع encoding="utf-8" حتى يظهر النص العربي طبيعيًا داخل ملف JSON.

5. محاولة قراءة ملف JSON فارغ

الملف الفارغ ليس JSON صالحًا، لذلك عالج JSONDecodeError وأعد قائمة فارغة.

6. الحذف دون تأكيد

اطلب من المستخدم تأكيدًا واضحًا قبل استخدام pop() حتى لا يحذف اسمًا بالخطأ.

7. اعتبار التحقق المبسط نهائيًا

فحص الهاتف والبريد في المثال مناسب للتعلم، لكنه ليس بديلًا عن قواعد أو مكتبات متخصصة في تطبيق حقيقي.

تحسينات يمكنك إضافتها لاحقًا

  • إضافة الشركة والعنوان والملاحظات.
  • البحث باستخدام رقم الهاتف.
  • ترتيب الأسماء أبجديًا قبل العرض.
  • منع تكرار رقم الهاتف.
  • تصدير البيانات إلى CSV.
  • إنشاء نسخة احتياطية من ملف JSON.
  • تقسيم البرنامج إلى أكثر من ملف.
  • كتابة اختبارات باستخدام pytest.
  • تحويل البرنامج إلى واجهة رسومية باستخدام Tkinter.

تمرين عملي

أضف المفتاح category لكل جهة اتصال، واجعل المستخدم يختار بين: العائلة، العمل، الأصدقاء، وأخرى. بعد ذلك أضف خيارًا يعرض جهات الاتصال حسب الفئة.

category = input(
    "أدخل الفئة: العائلة، العمل، الأصدقاء، أخرى: "
).strip()

contact = {
    "name": name,
    "phone": phone,
    "email": email,
    "category": category
}

روابط داخلية مفيدة من بايثون العرب

مصادر خارجية رسمية للتوسع

الخلاصة

أنشأنا برنامج دفتر جهات اتصال كاملًا باستخدام بايثون. خزّنا كل شخص داخل قاموس يحتوي على الاسم والهاتف والبريد، ثم وضعنا القواميس داخل قائمة واحدة.

تعلمنا الإضافة والعرض والبحث والتعديل والحذف، وقسمنا البرنامج إلى دوال واضحة. ثم استخدمنا مكتبة json لحفظ القائمة داخل ملف، وpathlib للمسار، وtry وexcept للتعامل مع مشكلات القراءة والكتابة.

{alertSuccess} القاعدة المهمة: البيانات الموجودة داخل المتغيرات تختفي عند انتهاء البرنامج. إذا أردت الاحتفاظ بها، احفظها في ملف أو قاعدة بيانات، ثم اقرأها عند التشغيل التالي.

أسئلة شائعة

كيف أنشئ برنامج جهات اتصال ببايثون؟

خزّن كل جهة اتصال داخل قاموس، وضع القواميس داخل قائمة، ثم أنشئ دوالًا للإضافة والعرض والبحث والتعديل والحذف.

لماذا استخدمنا JSON؟

لأنه مناسب للقوائم والقواميس، وسهل القراءة والكتابة باستخدام مكتبة json المدمجة مع بايثون.

هل أحتاج إلى تثبيت مكتبة json؟

لا. يكفي أن تكتب import json.

ما الفرق بين json.dump وjson.load؟

json.dump() تكتب بيانات بايثون داخل ملف، بينما json.load() تقرأ الملف وتحوله إلى بيانات بايثون.

كيف أمنع تكرار جهة الاتصال؟

ابحث عن الاسم أو رقم الهاتف قبل الإضافة. في المثال استخدمنا find_contact_index() لمنع تكرار الاسم.

هل يمكن البحث بجزء من الاسم؟

نعم، استخدم casefold() لتوحيد الحروف، ثم العامل in للتحقق من وجود النص داخل الاسم.

هل يمكن تحويل البرنامج إلى واجهة رسومية؟

نعم، يمكنك استخدام Tkinter لاحقًا مع الاحتفاظ بدوال الحفظ والقراءة نفسها تقريبًا.

هل JSON مناسب لعدد كبير من جهات الاتصال؟

هو مناسب للمشروع التعليمي والبيانات الصغيرة. عند نمو التطبيق، تكون قاعدة بيانات مثل SQLite أنسب للبحث والتعديل وإدارة البيانات.

إرسال تعليق

أحدث أقدم