جدولة سكريبتات بايثون: أتمت مهامك تلقائياً مع cron و schedule

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

في هذا الدليل العملي، ستتعلم طريقتين رئيسيتين لجدولة المهام: مكتبة schedule في بايثون، وأداة cron في لينكس/ماك. سنغطي أمثلة حقيقية تشمل جدولة النسخ الاحتياطي، إرسال الإيميلات الدورية، وتنظيف الملفات تلقائياً. هذا المقال جزء من سلسلة أتمتة المهام بلغة بايثون.

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

جدولة المهام ضرورية في سيناريوهات كثيرة:

  • النسخ الاحتياطي اليومي لقواعد البيانات أو الملفات المهمة
  • سحب بيانات دوري من مواقع أو APIs خارجية (مثل web scraping)
  • إرسال تقارير تلقائية عبر البريد الإلكتروني كل صباح
  • تنظيف الملفات المؤقتة أو ترتيب المجلدات أسبوعياً
  • مراقبة الخوادم وإرسال تنبيهات عند حدوث مشاكل
  • نشر محتوى على وسائل التواصل في أوقات محددة

الطريقة الأولى: مكتبة schedule في بايثون

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

التثبيت

pip install schedule

مثال أساسي: تنفيذ مهمة كل دقيقة

import schedule
import time
from datetime import datetime

def my_task():
    now = datetime.now().strftime("%H:%M:%S")
    print(f"[{now}] تم تنفيذ المهمة!")

# جدولة المهمة كل 5 دقائق
schedule.every(5).minutes.do(my_task)

# حلقة التشغيل
print("بدء الجدولة... اضغط Ctrl+C للإيقاف")
while True:
    schedule.run_pending()
    time.sleep(1)

أنماط جدولة متنوعة

مكتبة schedule توفر مرونة كبيرة في تحديد مواعيد التنفيذ:

import schedule

# كل 10 ثوانٍ
schedule.every(10).seconds.do(task)

# كل ساعة
schedule.every().hour.do(task)

# كل يوم الساعة 8 صباحاً
schedule.every().day.at("08:00").do(task)

# كل يوم اثنين الساعة 9 صباحاً
schedule.every().monday.at("09:00").do(task)

# كل 3 ساعات
schedule.every(3).hours.do(task)

# كل أسبوع
schedule.every().week.do(task)

مشروع عملي: نسخ احتياطي يومي تلقائي

لنبني سكريبت عملي يأخذ نسخة احتياطية من مجلد مهم كل يوم:

import schedule
import time
import shutil
import os
from datetime import datetime
import logging

# إعداد التسجيل
logging.basicConfig(
    filename="backup.log",
    level=logging.INFO,
    format="%(asctime)s - %(message)s"
)

SOURCE_DIR = "/path/to/important/data"
BACKUP_DIR = "/path/to/backups"

def daily_backup():
    """إنشاء نسخة احتياطية مضغوطة"""
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    backup_name = f"backup_{timestamp}"
    backup_path = os.path.join(BACKUP_DIR, backup_name)

    try:
        # إنشاء أرشيف مضغوط
        shutil.make_archive(backup_path, "zip", SOURCE_DIR)
        size = os.path.getsize(f"{backup_path}.zip")
        size_mb = size / (1024 * 1024)

        logging.info(f"نسخة احتياطية ناجحة: {backup_name}.zip ({size_mb:.1f} MB)")
        print(f"تم النسخ الاحتياطي: {backup_name}.zip ({size_mb:.1f} MB)")

        # حذف النسخ القديمة (أكثر من 7 أيام)
        cleanup_old_backups(BACKUP_DIR, days=7)

    except Exception as e:
        logging.error(f"فشل النسخ الاحتياطي: {e}")
        print(f"خطأ: {e}")

def cleanup_old_backups(backup_dir, days=7):
    """حذف النسخ الاحتياطية الأقدم من عدد أيام محدد"""
    now = time.time()
    cutoff = now - (days * 86400)

    for filename in os.listdir(backup_dir):
        filepath = os.path.join(backup_dir, filename)
        if os.path.getmtime(filepath) < cutoff:
            os.remove(filepath)
            logging.info(f"تم حذف نسخة قديمة: {filename}")

# جدولة النسخ الاحتياطي يومياً الساعة 2 صباحاً
schedule.every().day.at("02:00").do(daily_backup)

print("نظام النسخ الاحتياطي يعمل...")
while True:
    schedule.run_pending()
    time.sleep(60)

الطريقة الثانية: جدولة المهام بـ Cron (لينكس/ماك)

أداة cron هي أداة جدولة مدمجة في أنظمة لينكس وماك. ميزتها الرئيسية أنها تعمل على مستوى نظام التشغيل — أي أن السكريبت يُنفَّذ حتى لو لم تكن مسجلاً دخولك.

فهم صيغة Cron

تتكون صيغة cron من 5 حقول تحدد موعد التنفيذ:

# دقيقة  ساعة  يوم_الشهر  شهر  يوم_الأسبوع
#  (0-59) (0-23)  (1-31)   (1-12)  (0-6)

# كل يوم الساعة 8 صباحاً
0 8 * * *

# كل ساعة
0 * * * *

# كل يوم اثنين الساعة 9 صباحاً
0 9 * * 1

# كل 30 دقيقة
*/30 * * * *

# أول يوم من كل شهر الساعة منتصف الليل
0 0 1 * *

إضافة مهمة cron

لإضافة سكريبت بايثون لجدول cron:

# فتح محرر cron
crontab -e

# إضافة سطر لتنفيذ السكريبت يومياً الساعة 8 صباحاً
0 8 * * * /usr/bin/python3 /home/user/scripts/daily_report.py

# عرض المهام المجدولة
crontab -l
⚠️ نصيحة مهمة: استخدم المسار الكامل (absolute path) لكل من بايثون والسكريبت في cron. لمعرفة مسار بايثون، نفذ الأمر which python3 في الطرفية.

مشروع عملي: سكريبت مراقبة مع cron

لنبني سكريبت يتحقق من حالة موقع ويب كل 5 دقائق ويسجل النتائج:

#!/usr/bin/env python3
"""مراقبة حالة موقع ويب"""

import requests
import logging
import smtplib
from email.mime.text import MIMEText
from datetime import datetime

# الإعدادات
URLS_TO_MONITOR = [
    "https://example.com",
    "https://api.example.com/health",
]
ALERT_EMAIL = "admin@example.com"
LOG_FILE = "/var/log/site_monitor.log"

logging.basicConfig(
    filename=LOG_FILE,
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s"
)

def check_site(url, timeout=10):
    """فحص حالة موقع"""
    try:
        response = requests.get(url, timeout=timeout)
        if response.status_code == 200:
            logging.info(f"OK: {url} ({response.elapsed.total_seconds():.2f}s)")
            return True
        else:
            logging.warning(f"خطأ {response.status_code}: {url}")
            return False
    except requests.RequestException as e:
        logging.error(f"فشل الاتصال: {url} - {e}")
        return False

def send_alert(url, error_msg):
    """إرسال تنبيه بريدي"""
    msg = MIMEText(
        f"تنبيه: الموقع {url} لا يعمل!\n{error_msg}",
        "plain", "utf-8"
    )
    msg["Subject"] = f"تنبيه: {url} معطل!"
    # ... إرسال الإيميل (راجع مقال أتمتة البريد)

# الفحص
for url in URLS_TO_MONITOR:
    if not check_site(url):
        send_alert(url, "الموقع لا يستجيب")

أضف هذا السكريبت لـ cron ليعمل كل 5 دقائق:

*/5 * * * * /usr/bin/python3 /home/user/scripts/monitor.py

الطريقة الثالثة: Task Scheduler في ويندوز

إذا كنت تستخدم ويندوز، يمكنك استخدام Task Scheduler لجدولة سكريبتات بايثون:

# إنشاء مهمة مجدولة عبر PowerShell
$action = New-ScheduledTaskAction `
    -Execute "python" `
    -Argument "C:\scripts\daily_task.py" `
    -WorkingDirectory "C:\scripts"

$trigger = New-ScheduledTaskTrigger `
    -Daily -At "08:00AM"

Register-ScheduledTask `
    -TaskName "PythonDailyTask" `
    -Action $action `
    -Trigger $trigger `
    -Description "تنفيذ سكريبت بايثون يومياً"

مقارنة بين طرق الجدولة

الميزةschedule (بايثون)cron (لينكس)Task Scheduler (ويندوز)
سهولة الإعدادسهل جداًمتوسطمتوسط
يعمل بدون تسجيل دخوللانعمنعم
دقة التوقيتثوانٍدقائقدقائق
إدارة الأخطاءكود بايثونسجلات النظامواجهة رسومية
الأفضل لـالتطوير والاختبارسيرفرات الإنتاجأجهزة ويندوز

نصائح وأفضل الممارسات

  • سجّل كل شيء (Logging): أضف تسجيلاً مفصلاً لكل مهمة حتى تتمكن من تتبع المشاكل
  • تعامل مع الأخطاء: لا تترك السكريبت يتوقف عند أول خطأ — استخدم try/except
  • أرسل تنبيهات: عند فشل مهمة مهمة، أرسل إيميل تنبيه فوراً
  • استخدم Virtual Environment: تأكد أن cron يستخدم بيئة بايثون الصحيحة
  • اختبر يدوياً أولاً: شغّل السكريبت يدوياً قبل جدولته للتأكد من عمله
  • تجنب التداخل: تأكد أن المهمة لا تبدأ قبل انتهاء التنفيذ السابق
💡 للمحترفين: إذا كنت تعمل على مشاريع كبيرة، فكّر في استخدام أدوات متقدمة مثل Celery أو Apache Airflow لإدارة المهام المعقدة والموزعة.

الخلاصة

تعلمنا في هذا المقال كيفية جدولة سكريبتات بايثون بثلاث طرق مختلفة: مكتبة schedule للجدولة من داخل بايثون، وcron لأنظمة لينكس/ماك، وTask Scheduler لويندوز. الجدولة هي المفتاح لتحويل سكريبتاتك من أدوات يدوية إلى أنظمة أتمتة تعمل بشكل مستمر.

لاستكمال مهاراتك في أتمتة بايثون، اطلع على باقي مقالات السلسلة:

تعليقات

المشاركات الشائعة من هذه المدونة

تعلم Git و GitHub للمبتدئين: دليل شامل بالعربي خطوة بخطوة (2026)

تعلم بايثون من الصفر 2026: دليل شامل للمبتدئين

دليل الصحة النفسية 2026: كيف تتعامل مع القلق والاكتئاب وتعيش حياة متوازنة