بعد أن تتعلم أساسيات Python مثل المتغيرات، الشروط، الحلقات، الدوال، القوائم، القواميس، وقراءة الملفات، ستحتاج إلى خطوة مهمة تنقلك من كتابة أمثلة صغيرة إلى بناء برامج عملية يمكن تشغيلها من سطر الأوامر. هذه الخطوة هي بناء برنامج CLI.
كلمة CLI هي اختصار لعبارة Command Line Interface، وتعني واجهة سطر الأوامر. بدل أن يستخدم الشخص أزرارًا ونوافذ رسومية، يتعامل مع البرنامج من خلال أوامر يكتبها في Terminal أو CMD أو PowerShell.
في هذا الدرس من سلسلة بايثون بعد الأساسيات على موقع بايثون العرب سنتعلم بناء برنامج سطر أوامر بسيط في Python خطوة بخطوة. سنبدأ بفكرة بسيطة باستخدام input()، ثم ننتقل إلى طريقة أفضل باستخدام مكتبة argparse المدمجة مع Python، ثم ننظم المشروع ونضيف رسائل أوضح للمستخدم.
{getToc} $title={محتوى المقال}
الفكرة ببساطة: برنامج CLI هو برنامج تشغله من Terminal وتتحكم فيه بالأوامر والخيارات. في البداية يمكنك استخدامinput()، لكن للمشاريع الأفضل استخدمargparse. {alertInfo}
ما هو برنامج CLI في Python؟
برنامج CLI هو برنامج يعمل من خلال سطر الأوامر. مثلًا بدل أن تفتح نافذة فيها زر "تشغيل"، تكتب أمرًا مثل:
python main.py
أو:
python main.py --name Ali
أو:
python main.py add "تعلم Python"
هذه الطريقة مفيدة جدًا في الأدوات الصغيرة، برامج الأتمتة، معالجة الملفات، إدارة المهام، قراءة CSV، تحويل صيغ البيانات، أو بناء أدوات يستخدمها المطورون من الطرفية.
لماذا نتعلم بناء برامج CLI؟
تعلم بناء برامج سطر الأوامر يساعدك على فهم Python بطريقة عملية أكثر، لأنك ستبدأ في التفكير مثل المطورين:
- كيف يستقبل البرنامج أوامر من المستخدم؟
- كيف أعالج الخيارات المختلفة؟
- كيف أرتب الملفات داخل المشروع؟
- كيف أجعل البرنامج واضحًا عند الاستخدام؟
- كيف أتعامل مع الأخطاء بدل توقف البرنامج فجأة؟
- كيف أجعل الأداة قابلة للتطوير لاحقًا؟
برامج CLI ليست للخبراء فقط. هي من أفضل المشاريع الصغيرة بعد تعلم الأساسيات؛ لأنها تجمع بين الدوال، الشروط، القواميس، القوائم، الملفات، ورسائل الأخطاء في مشروع واحد.
أمثلة على أدوات CLI حقيقية
ربما استخدمت من قبل أوامر مثل:
python --version
pip install requests
git status
npm install
django-admin startproject mysite
كل هذه أمثلة على أدوات تعمل من سطر الأوامر. أنت أيضًا يمكنك بناء أدوات صغيرة بنفس الفكرة باستخدام Python.
متى أستخدم CLI بدل الواجهة الرسومية؟
استخدم CLI عندما تريد أداة:
- سريعة وخفيفة.
- لا تحتاج إلى تصميم واجهة رسومية.
- مناسبة للتشغيل المتكرر.
- تتعامل مع ملفات أو بيانات.
- يمكن استخدامها داخل سكربتات أخرى.
- مناسبة للمطورين أو لنفسك أثناء العمل.
أما الواجهة الرسومية فتكون مناسبة إذا كان المستخدم النهائي لا يعرف سطر الأوامر أو يحتاج أزرارًا وشاشات واضحة.
المرحلة الأولى: برنامج CLI بسيط باستخدام input
قبل أن ندخل إلى argparse، لنبدأ بطريقة بسيطة يعرفها أغلب المبتدئين: input().
سنكتب برنامجًا يطلب اسم المستخدم ثم يطبع رسالة ترحيب.
name = input("اكتب اسمك: ")
print("مرحبًا", name)
عند التشغيل:
python main.py
سيطلب منك البرنامج إدخال الاسم:
اكتب اسمك: Ali
مرحبًا Ali
هذه طريقة سهلة، لكنها ليست دائمًا الأفضل لأدوات سطر الأوامر؛ لأن المستخدم لا يستطيع تمرير الخيارات مباشرة مع الأمر.
ما مشكلة input في برامج CLI؟
استخدام input() مفيد للتفاعل البسيط، لكنه قد يكون محدودًا في الأدوات العملية. مثلًا، لا يمكنك تشغيل البرنامج بهذا الشكل:
python main.py --name Ali
لأن البرنامج ينتظر منك إدخالًا بعد التشغيل. في أدوات CLI الأفضل أن يستطيع المستخدم تمرير القيم مباشرة مع الأمر.
لهذا نستخدم مكتبة argparse.
ما هي مكتبة argparse؟
مكتبة argparse مكتبة مدمجة مع Python، أي لا تحتاج إلى تثبيتها. وظيفتها أن تساعدك على استقبال أوامر وخيارات من سطر الأوامر.
بدل أن تجعل البرنامج يسأل المستخدم:
اكتب اسمك:
يمكنك جعله يقبل الأمر هكذا:
python main.py --name Ali
ثم يقرأ البرنامج قيمة --name ويستخدمها.
أول برنامج CLI باستخدام argparse
أنشئ ملفًا باسم main.py واكتب:
import argparse
parser = argparse.ArgumentParser(
description="برنامج ترحيب بسيط باستخدام Python CLI"
)
parser.add_argument(
"--name",
required=True,
help="اسم المستخدم"
)
args = parser.parse_args()
print("مرحبًا", args.name)
شغل البرنامج:
python main.py --name Ali
الناتج:
مرحبًا Ali
شرح الكود خطوة بخطوة
السطر الأول:
import argparse
نستورد مكتبة argparse.
ثم ننشئ كائنًا اسمه parser:
parser = argparse.ArgumentParser(
description="برنامج ترحيب بسيط باستخدام Python CLI"
)
هذا الكائن مسؤول عن تعريف الخيارات وقراءة ما يكتبه المستخدم في Terminal.
ثم نضيف خيارًا:
parser.add_argument(
"--name",
required=True,
help="اسم المستخدم"
)
معناه أن البرنامج يقبل خيارًا اسمه --name، وهذا الخيار مطلوب لأننا وضعنا required=True.
ثم نقرأ القيم:
args = parser.parse_args()
بعدها نستطيع الوصول إلى الاسم من خلال:
args.name
ميزة help في برامج CLI
من أجمل ميزات argparse أنها تنشئ صفحة مساعدة تلقائيًا.
جرّب:
python main.py --help
ستظهر لك رسالة توضح طريقة استخدام البرنامج والخيارات المتاحة.
هذا مهم جدًا؛ لأن برنامج CLI الجيد يجب أن يشرح نفسه للمستخدم.
إضافة خيار غير إجباري
لنفترض أننا نريد إضافة خيار --lang لتحديد لغة الرسالة، لكنه ليس إجباريًا.
import argparse
parser = argparse.ArgumentParser(
description="برنامج ترحيب بسيط"
)
parser.add_argument("--name", required=True, help="اسم المستخدم")
parser.add_argument("--lang", default="ar", help="لغة الرسالة: ar أو en")
args = parser.parse_args()
if args.lang == "en":
print("Hello", args.name)
else:
print("مرحبًا", args.name)
التشغيل بالعربية:
python main.py --name Ali
الناتج:
مرحبًا Ali
التشغيل بالإنجليزية:
python main.py --name Ali --lang en
الناتج:
Hello Ali
تحديد قيم مسموحة باستخدام choices
بدل أن نترك المستخدم يكتب أي قيمة في --lang، يمكننا تحديد القيم المسموحة:
parser.add_argument(
"--lang",
choices=["ar", "en"],
default="ar",
help="لغة الرسالة"
)
إذا كتب المستخدم قيمة غير مسموحة، ستعرض argparse رسالة خطأ واضحة.
بناء مشروع CLI منظم
بدل وضع كل شيء عشوائيًا، دعنا ننشئ مجلد مشروع بسيط:
simple_cli/
│
├── main.py
├── README.md
└── data/
└── tasks.txt
في البداية يمكن أن يكون المشروع بملف واحد فقط، لكن التنظيم من الآن يساعدك عندما يكبر البرنامج.
مشروع عملي: برنامج مهام CLI بسيط
الآن سنبني برنامجًا عمليًا صغيرًا لإدارة المهام من سطر الأوامر. البرنامج سيقوم بثلاث عمليات:
- إضافة مهمة جديدة.
- عرض كل المهام.
- مسح كل المهام.
سنستخدم ملفًا نصيًا بسيطًا لتخزين المهام.
الفكرة العامة للبرنامج
نريد أن يعمل البرنامج بهذه الطريقة:
python main.py add "تعلم argparse"
python main.py list
python main.py clear
الأمر add يضيف مهمة، والأمر list يعرض المهام، والأمر clear يمسحها.
الكود الكامل لبرنامج المهام CLI
اكتب هذا الكود داخل main.py:
import argparse
from pathlib import Path
DATA_DIR = Path("data")
TASKS_FILE = DATA_DIR / "tasks.txt"
def prepare_storage():
DATA_DIR.mkdir(exist_ok=True)
TASKS_FILE.touch(exist_ok=True)
def add_task(task):
prepare_storage()
with TASKS_FILE.open("a", encoding="utf-8") as file:
file.write(task + "\n")
print("تمت إضافة المهمة:", task)
def list_tasks():
prepare_storage()
with TASKS_FILE.open("r", encoding="utf-8") as file:
tasks = [line.strip() for line in file if line.strip()]
if not tasks:
print("لا توجد مهام حاليًا.")
return
print("قائمة المهام:")
for index, task in enumerate(tasks, start=1):
print(f"{index}. {task}")
def clear_tasks():
prepare_storage()
TASKS_FILE.write_text("", encoding="utf-8")
print("تم مسح جميع المهام.")
def main():
parser = argparse.ArgumentParser(
description="برنامج مهام بسيط يعمل من سطر الأوامر"
)
subparsers = parser.add_subparsers(
dest="command",
required=True
)
add_parser = subparsers.add_parser("add", help="إضافة مهمة جديدة")
add_parser.add_argument("task", help="نص المهمة")
subparsers.add_parser("list", help="عرض المهام")
subparsers.add_parser("clear", help="مسح كل المهام")
args = parser.parse_args()
if args.command == "add":
add_task(args.task)
elif args.command == "list":
list_tasks()
elif args.command == "clear":
clear_tasks()
if __name__ == "__main__":
main()
تشغيل برنامج المهام
لإضافة مهمة:
python main.py add "تعلم بناء CLI في Python"
الناتج:
تمت إضافة المهمة: تعلم بناء CLI في Python
لعرض المهام:
python main.py list
الناتج:
قائمة المهام:
1. تعلم بناء CLI في Python
لمسح المهام:
python main.py clear
الناتج:
تم مسح جميع المهام.
ما معنى subcommands في argparse؟
في برنامجنا استخدمنا أوامر فرعية مثل:
add
list
clear
هذه تسمى subcommands أو أوامر فرعية. وهي مفيدة عندما يكون البرنامج فيه أكثر من عملية.
مثلًا:
addلإضافة مهمة.listلعرض المهام.clearلمسح المهام.
وهذا يشبه أدوات حقيقية مثل:
git add
git commit
git status
لماذا استخدمنا pathlib؟
استخدمنا pathlib للتعامل مع المسارات بطريقة أوضح:
from pathlib import Path
ثم:
DATA_DIR = Path("data")
TASKS_FILE = DATA_DIR / "tasks.txt"
هذه الطريقة أفضل من كتابة المسار كسلسلة نصية طويلة، وتعمل بشكل أوضح مع Windows و Linux و macOS.
إذا لم تكن مرتاحًا مع pathlib بعد، راجع:
شرح pathlib في Python للتعامل مع الملفات والمجلدات.
شرح دالة prepare_storage
الدالة:
def prepare_storage():
DATA_DIR.mkdir(exist_ok=True)
TASKS_FILE.touch(exist_ok=True)
تقوم بعملين:
- إنشاء مجلد
dataإذا لم يكن موجودًا. - إنشاء ملف
tasks.txtإذا لم يكن موجودًا.
استخدمنا exist_ok=True حتى لا يظهر خطأ إذا كان المجلد أو الملف موجودًا مسبقًا.
شرح دالة add_task
هذه الدالة تضيف مهمة إلى الملف:
def add_task(task):
prepare_storage()
with TASKS_FILE.open("a", encoding="utf-8") as file:
file.write(task + "\n")
استخدمنا الوضع "a" لأنه يعني append، أي الإضافة في نهاية الملف بدل مسح المحتوى القديم.
شرح دالة list_tasks
هذه الدالة تقرأ كل المهام من الملف:
with TASKS_FILE.open("r", encoding="utf-8") as file:
tasks = [line.strip() for line in file if line.strip()]
استخدمنا strip() لحذف الفراغات ونهاية السطر \n.
ثم عرضنا المهام بالأرقام:
for index, task in enumerate(tasks, start=1):
print(f"{index}. {task}")
الدالة enumerate() تساعدنا على الحصول على رقم العنصر وقيمته في نفس الوقت.
شرح دالة clear_tasks
هذه الدالة تمسح محتوى الملف:
TASKS_FILE.write_text("", encoding="utf-8")
كتابة نص فارغ داخل الملف تعني حذف كل المهام القديمة.
إضافة تأكيد قبل المسح
قد يكون من الأفضل أن تطلب تأكيدًا من المستخدم قبل مسح كل المهام.
def clear_tasks():
prepare_storage()
answer = input("هل أنت متأكد من مسح كل المهام؟ yes/no: ")
if answer.lower() != "yes":
print("تم إلغاء العملية.")
return
TASKS_FILE.write_text("", encoding="utf-8")
print("تم مسح جميع المهام.")
هنا جمعنا بين argparse و input(). لا مانع من ذلك عند الحاجة.
إضافة أمر count لحساب عدد المهام
يمكنك تطوير البرنامج بإضافة أمر جديد اسمه count.
أولًا أضف دالة:
def count_tasks():
prepare_storage()
with TASKS_FILE.open("r", encoding="utf-8") as file:
tasks = [line for line in file if line.strip()]
print("عدد المهام:", len(tasks))
ثم أضف الأمر:
subparsers.add_parser("count", help="عرض عدد المهام")
ثم داخل الشروط:
elif args.command == "count":
count_tasks()
التشغيل:
python main.py count
التعامل مع الأخطاء في برنامج CLI
برنامج CLI الجيد لا يجب أن يعرض للمستخدم رسائل أخطاء طويلة دائمًا. أحيانًا نحتاج إلى رسائل واضحة.
مثال: عند محاولة قراءة ملف قد تظهر أخطاء مثل:
FileNotFoundErrorPermissionErrorUnicodeDecodeError
في برنامجنا أنشأنا الملف تلقائيًا لتجنب FileNotFoundError. لكن في برامج أكبر يجب أن تتعامل مع الأخطاء المتوقعة.
try:
content = TASKS_FILE.read_text(encoding="utf-8")
except PermissionError:
print("لا توجد صلاحية لقراءة ملف المهام.")
راجع أيضًا: شرح try و except في Python للمبتدئين و حل خطأ PermissionError في Python عند فتح الملفات.
استخدام exit code في برامج CLI
في الأدوات العملية، قد تحتاج إلى إرجاع رمز خروج يوضح هل نجح البرنامج أم فشل. عادة:
0يعني نجاح.- أي رقم غير
0يعني وجود مشكلة.
مثال بسيط:
import sys
if not TASKS_FILE.exists():
print("ملف المهام غير موجود.")
sys.exit(1)
sys.exit(0)
هذه فكرة متقدمة قليلًا، لكنها مهمة إذا أردت بناء أدوات يستخدمها الآخرون أو تعمل داخل سكربتات تلقائية.
كيف تجعل برنامجك أسهل في الاستخدام؟
برنامج CLI الجيد يجب أن يكون واضحًا. لذلك اهتم بـ:
- اسم أمر واضح.
- وصف قصير داخل
description. - رسائل help مفهومة.
- رسائل نجاح واضحة.
- رسائل خطأ لا تخيف المستخدم.
- أمثلة استخدام داخل README.
مثال README بسيط:
# Simple CLI Tasks
برنامج مهام بسيط باستخدام Python.
## التشغيل
إضافة مهمة:
python main.py add "تعلم Python"
عرض المهام:
python main.py list
مسح المهام:
python main.py clear
أفضل ممارسات بناء CLI في Python
- ابدأ ببرنامج صغير وواضح.
- استخدم
argparseللأدوات العملية بدل الاعتماد الكامل علىinput(). - اكتب أسماء أوامر مفهومة مثل
addوlistوclear. - استخدم
--helpوتأكد أن الرسائل واضحة. - افصل الكود إلى دوال بدل وضع كل شيء داخل مكان واحد.
- استخدم
pathlibللتعامل مع الملفات والمجلدات. - استخدم
encoding="utf-8"عند قراءة وكتابة النصوص. - تعامل مع الأخطاء المتوقعة برسائل بسيطة.
- لا تجعل البرنامج يمسح بيانات مهمة بدون تأكيد.
- اكتب ملف README يشرح طريقة الاستخدام.
أخطاء شائعة عند بناء برنامج CLI
1. نسيان إضافة help
لا تجعل المستخدم يخمن طريقة تشغيل البرنامج. أضف وصفًا لكل خيار.
2. وضع كل الكود في مكان واحد
استخدم دوال مثل add_task() و list_tasks() و clear_tasks() حتى يبقى الكود واضحًا.
3. عدم التعامل مع الملفات بشكل آمن
استخدم with عند فتح الملفات، واستخدم encoding="utf-8" لتجنب مشاكل الترميز.
4. عدم اختبار الأوامر المختلفة
جرّب كل أمر:
python main.py --help
python main.py add "Test"
python main.py list
python main.py clear
5. استخدام أسماء أوامر غير واضحة
الأمر add أوضح من a للمبتدئين، و list أوضح من ls في البرامج التعليمية.
كيف تطور هذا المشروع لاحقًا؟
بعد فهم المشروع الأساسي، يمكنك تطويره بطرق كثيرة:
- إضافة أمر لحذف مهمة محددة برقمها.
- إضافة أمر لتعديل مهمة.
- إضافة حالة للمهمة: مكتملة أو غير مكتملة.
- حفظ البيانات في JSON بدل TXT.
- حفظ البيانات في CSV.
- إضافة تاريخ إنشاء المهمة.
- إضافة ألوان للرسائل باستخدام مكتبات خارجية لاحقًا.
- تحويل المشروع إلى حزمة قابلة للتثبيت.
يمكنك ربط هذا الدرس بدروس: شرح مكتبة json في Python و شرح ملفات CSV في Python إذا أردت تخزين المهام بطريقة منظمة أكثر.
تدريب عملي
بعد تطبيق البرنامج، حاول تنفيذ التعديلات التالية:
- أضف أمرًا جديدًا باسم
countيعرض عدد المهام. - أضف تأكيدًا قبل تنفيذ أمر
clear. - اجعل أمر
addيرفض المهمة الفارغة. - أضف ملف
README.mdفيه أمثلة تشغيل. - جرّب تشغيل
python main.py --helpولاحظ صفحة المساعدة.
حل مختصر: منع إضافة مهمة فارغة
يمكنك تعديل دالة add_task بهذا الشكل:
def add_task(task):
task = task.strip()
if not task:
print("لا يمكن إضافة مهمة فارغة.")
return
prepare_storage()
with TASKS_FILE.open("a", encoding="utf-8") as file:
file.write(task + "\n")
print("تمت إضافة المهمة:", task)
استخدمنا strip() لحذف الفراغات، ثم تحققنا هل النص فارغ أم لا.
روابط داخلية مفيدة من بايثون العرب
- كورس أساسيات بايثون للمبتدئين
- بايثون بعد الأساسيات 2: تنظيم ملفات مشروع Python
- بايثون بعد الأساسيات 3: قراءة وكتابة ملفات CSV داخل مشروع Python
- أساسيات بايثون 31: شرح try و except في Python
- أساسيات بايثون 32: شرح أخطاء Python وقراءة رسائل الخطأ
- شرح pathlib في Python للتعامل مع الملفات والمجلدات
- أساسيات بايثون 29: شرح مكتبة json في Python
- أساسيات بايثون 30: شرح ملفات CSV في Python
مصادر خارجية مفيدة للتوسع
- توثيق Python الرسمي لمكتبة argparse
- توثيق Python الرسمي لمكتبة pathlib
- توثيق Python الرسمي لمكتبة sys
- توثيق Python الرسمي حول قراءة وكتابة الملفات
الخلاصة
بناء برنامج سطر أوامر CLI بسيط في Python خطوة ممتازة بعد تعلم الأساسيات؛ لأنها تجمع بين الدوال، الشروط، الملفات، تنظيم المشروع، والتعامل مع مدخلات المستخدم بطريقة عملية.
بدأنا بطريقة بسيطة باستخدام input()، ثم تعلمنا استخدام argparse لاستقبال الخيارات والأوامر من Terminal. بعد ذلك بنينا برنامج مهام بسيط يدعم أوامر add و list و clear، وتعلمنا كيف ننظم المشروع ونتعامل مع الملفات باستخدام pathlib.
الخلاصة العملية: إذا أردت بناء أداة Python صغيرة تعمل من Terminal، ابدأ بـ argparse، قسّم الكود إلى دوال، أضف رسائل help واضحة، وتعامل مع الملفات والأخطاء بعناية. {alertSuccess}
أسئلة شائعة مع إجاباتها
ما معنى CLI في Python؟
يعني برنامج يعمل من خلال سطر الأوامر، حيث يكتب المستخدم أوامر وخيارات في Terminal لتشغيل وظائف البرنامج.
هل أحتاج مكتبة خارجية لبناء CLI في Python؟
لا. يمكنك استخدام مكتبة argparse المدمجة مع Python لبناء أدوات CLI جيدة بدون تثبيت مكتبات إضافية.
ما الفرق بين input و argparse؟
input() يطلب من المستخدم إدخال قيمة أثناء تشغيل البرنامج، أما argparse فيقرأ القيم والخيارات مباشرة من الأمر المكتوب في Terminal.
متى أستخدم argparse؟
استخدمه عندما تريد بناء أداة تقبل خيارات مثل --name أو أوامر مثل add و list.
هل برنامج CLI مناسب للمبتدئين؟
نعم، خصوصًا بعد تعلم الأساسيات. هو مشروع ممتاز للتدريب على الدوال والملفات والشروط وتنظيم الكود.
كيف أجعل برنامج CLI أكثر احترافية؟
أضف صفحة مساعدة واضحة، قسّم الكود إلى دوال، تعامل مع الأخطاء، واكتب ملف README يشرح طريقة التشغيل.
هل يمكن تخزين بيانات CLI في JSON أو CSV؟
نعم. في البداية استخدم ملف TXT بسيط، ثم يمكنك تطوير البرنامج لاحقًا ليستخدم JSON أو CSV حسب نوع البيانات.



