الفصل الثاني عشر: المكتبات الخارجية والبيئات الافتراضية
مقدمة الفصل
لقد استكشفنا في الفصل السابق الأدوات القوية التي تأتي مدمجة مع بايثون في مكتبتها القياسية. الآن، حان الوقت لفتح الباب أمام القوة الحقيقية لمجتمع بايثون: النظام البيئي الهائل للمكتبات الخارجية (External Libraries). هذه المكتبات هي التي تجعل من بايثون اللغة الأولى في مجالات مثل علم البيانات والذكاء الاصطناعي وتطوير الويب.
لكن قبل أن نبدأ بتثبيت هذه الأدوات، يجب أن نتعلم أولاً كيف نحافظ على تنظيم مشاريعنا. عندما تعمل على مشاريع مختلفة، قد يحتاج كل مشروع إلى إصدارات مختلفة من نفس المكتبة. فكيف نمنع حدوث تضارب بينها؟ الحل يكمن في البيئات الافتراضية (Virtual Environments).
في هذا الفصل، سنتعلم الممارسة الاحترافية لإدارة المشاريع:
- إنشاء بيئات معزولة لكل مشروع.
- استخدام مدير الحزم
pip
لتثبيت المكتبات داخل هذه البيئات. - استكشاف بعض المكتبات الخارجية التي ستغير طريقة برمجتك.
1. البيئات الافتراضية: تنظيم مساحة عملك
تخيل أنك تعمل على مشروعين:
- المشروع أ: يتطلب مكتبة تحليل بيانات بالإصدار 1.0.
- المشروع ب: هو مشروع أحدث ويتطلب نفس المكتبة ولكن بالإصدار 2.0.
إذا قمت بتثبيت المكتبات على نظامك مباشرة، فستواجه مشكلة. لا يمكنك تثبيت إصدارين مختلفين من نفس المكتبة في نفس الوقت. هذا ما يسمى بـ “جحيم الاعتماديات” (Dependency Hell).
الحل هو البيئة الافتراضية. البيئة الافتراضية هي نسخة معزولة ومستقلة من بايثون ومكتباتها، خاصة بمشروع واحد فقط. عندما تنشئ بيئة افتراضية لمشروعك، فإن أي مكتبة تقوم بتثبيتها ستكون موجودة فقط داخل هذه البيئة، ولن تؤثر على مشاريعك الأخرى أو على بايثون المثبت على نظامك.
إنها أفضل ممارسة يجب على كل مبرمج بايثون اتباعها.
كيفية إنشاء وتفعيل بيئة افتراضية
تحتوي بايثون على وحدة مدمجة اسمها venv
لإنشاء البيئات الافتراضية.
أولاً، سنقوم بإنشاء البيئة. افتح سطر الأوامر (Terminal أو Command Prompt)، اذهب إلى مجلد مشروعك، ثم نفذ الأمر التالي لإنشاء مجلد بيئة افتراضية باسم venv
.
python -m venv venv
ثانياً، يجب عليك “تفعيل” البيئة في كل مرة تريد العمل على مشروعك. طريقة التفعيل تختلف قليلاً بين أنظمة التشغيل.
- على Windows:
venv\Scripts\activate
- على macOS و Linux:
source venv/bin/activate
عند تفعيل البيئة، ستلاحظ أن اسم البيئة (venv
) يظهر في بداية سطر الأوامر. هذا يعني أنك الآن تعمل داخل هذه البيئة المعزولة.
ثالثاً، عندما تنتهي من العمل على مشروعك، يمكنك الخروج من البيئة الافتراضية ببساطة عن طريق كتابة الأمر deactivate
.
deactivate
2. pip
: مدير حزم بايثون
الآن بعد أن أصبحت داخل بيئتك الافتراضية المفعلة، يمكنك استخدام pip
بأمان لتثبيت المكتبات التي يحتاجها مشروعك فقط. pip
هي الأداة الرسمية التي تتصل بمستودع ضخم على الإنترنت يسمى Python Package Index (PyPI) لجلب وتثبيت المكتبات.
أ. تثبيت مكتبة
سنقوم الآن بتثبيت مكتبة requests
، والتي تستخدم لإجراء طلبات HTTP.
pip install requests
ب. عرض المكتبات المثبتة
لمعرفة كل المكتبات الخارجية المثبتة في بيئتك الحالية، استخدم الأمر pip list
.
pip list
3. استكشاف مكتبة requests
مع DummyJSON API
هذه هي أشهر مكتبة لجعل التواصل مع الإنترنت وواجهات برمجة التطبيقات (APIs) أمرًا بسيطًا للغاية. سنقوم الآن بكتابة سكربت لجلب بيانات منتجات من واجهة برمجة تطبيقات عامة وموثوقة.
الخطوة الأولى: استيراد المكتبة وتحديد عنوان الـ API
في بداية السكربت، يجب استيراد المكتبة التي قمنا بتثبيتها. ثم، سنقوم بتعريف عنوان الـ API الذي نريد الوصول إليه في متغير. سنستخدم dummyjson.com
التي توفر بيانات وهمية ممتازة للتجربة.
import requests
api_url = "https://dummyjson.com/products/1"
الخطوة الثانية: إرسال الطلب ومعالجة الأخطاء المحتملة
سنضع الكود الذي يتصل بالإنترنت داخل كتلة try...except
للتعامل مع أي مشاكل في الاتصال. سنستخدم دالة get
من مكتبة requests
لإرسال الطلب، وسيتم تخزين كل معلومات الاستجابة في متغير اسمه response
.
try:
response = requests.get(api_url)
# This line will raise an exception for bad status codes (like 404 or 500)
response.raise_for_status()
except requests.exceptions.RequestException as e:
print(f"An error occurred with the request: {e}")
الخطوة الثالثة: التحقق من نجاح الاستجابة وتحويل البيانات
بعد التأكد من عدم وجود أخطاء في الاتصال، يجب أن نتحقق من أن الطلب نفسه كان ناجحًا. الرمز 200
هو الرمز القياسي للنجاح في بروتوكول HTTP. بعد ذلك، سنستخدم دالة json
المدمجة في كائن الاستجابة، والتي تقوم بتحويل النص القادم من الـ API (والذي يكون بصيغة JSON) إلى قاموس بايثون يمكننا التعامل معه بسهولة.
data = None
if response.status_code == 200:
data = response.json()
else:
print(f"Error: Failed to retrieve data. Status code: {response.status_code}")
الخطوة الرابعة: استخراج وعرض المعلومات الآن بعد أن أصبح لدينا قاموس بايثون، نستخدم المفاتيح للوصول إلى البيانات التي نريدها بالضبط، وفي هذه الحالة هي عنوان المنتج وسعره.
if data:
product_title = data.get('title')
product_price = data.get('price')
if product_title and product_price:
print(f"Successfully fetched product data:")
print(f"Product Title: {product_title}")
print(f"Product Price: ${product_price}")
else:
print("Could not find title or price in the response.")
4. إدارة المشاريع باستخدام requirements.txt
عندما تعمل على مشروع وتود مشاركته مع آخرين، كيف تضمن أنهم سيقومون بتثبيت نفس المكتبات التي استخدمتها؟ الحل هو ملف requirements.txt
.
لإنشاء هذا الملف، تأكد من أن بيئتك الافتراضية مفعلة، ثم نفذ الأمر التالي. سيقوم هذا الأمر بحفظ قائمة بكل المكتبات المثبتة في بيئتك الحالية داخل الملف.
pip freeze > requirements.txt
عندما يحصل شخص آخر على مشروعك، كل ما عليه فعله لتثبيت كل المكتبات المطلوبة هو إنشاء بيئته الافتراضية الخاصة، تفعيلها، ثم تشغيل أمر واحد:
pip install -r requirements.txt
5. تمرين تطبيقي: البحث عن منتجات حسب الفئة
المطلوب:
كتابة برنامج يتفاعل مع dummyjson.com
API للبحث عن منتجات تنتمي إلى فئة معينة يحددها المستخدم. هذا التمرين سيجعلك تطبق كل ما تعلمته: إعداد البيئة، تثبيت مكتبة، التفاعل مع API، ومعالجة البيانات المستلمة.
إرشادات الحل:
- إعداد بيئة المشروع: قم بإنشاء مجلد جديد، ثم أنشئ وفعّل بيئة افتراضية، وقم بتثبيت مكتبة
requests
بداخلها. - عنوان الـ API: استخدم الرابط التالي لجلب كل المنتجات:
https://dummyjson.com/products
. - مدخلات المستخدم: اطلب من المستخدم إدخال اسم فئة المنتجات التي يرغب في البحث عنها (مثلاً:
smartphones
,laptops
,fragrances
). - كتابة السكربت:
- أرسل طلب
get
إلى الـ API لجلب قائمة كل المنتجات. - تأكد من أن الطلب كان ناجحًا وقم بتحويل الاستجابة إلى قاموس بايثون.
- البيانات التي تهمك ستكون موجودة داخل المفتاح
'products'
، وهي عبارة عن قائمة من القواميس. - قم بكتابة حلقة
for
للتكرار على هذه القائمة. - داخل الحلقة، استخدم جملة
if
للتحقق مما إذا كانت قيمة المفتاح'category'
للمنتج الحالي تطابق الفئة التي أدخلها المستخدم. - إذا تطابقت، اطبع اسم المنتج وسعره.
- أرسل طلب
- رسالة في حال عدم العثور: إذا انتهت الحلقة دون العثور على أي منتجات، اطبع رسالة للمستخدم تفيد بعدم العثور على منتجات في هذه الفئة.
حاول حل التمرين بنفسك قبل الاطلاع على الحل المقترح في الصفحة التالية.
الحل المقترح للتمرين
الخطوة 1: إعداد بيئة المشروع من سطر الأوامر (هذه الخطوة تُنفذ مرة واحدة في بداية المشروع)
mkdir product_searcher
cd product_searcher
python -m venv venv
# For Windows: venv\Scripts\activate
# For macOS/Linux: source venv/bin/activate
pip install requests
شرح الخطوة 1: بهذه الأوامر، قمنا بإنشاء مساحة عمل معزولة ونظيفة لمشروعنا، وقمنا بتثبيت المكتبة التي سنحتاجها.
الخطوة 2: كتابة سكربت بايثون (ملف search_app.py
)
الآن، أنشئ ملف search_app.py
واكتب بداخله الكود التالي.
أولاً، سنقوم باستيراد المكتبة، تحديد عنوان الـ API، وطلب الفئة من المستخدم.
import requests
# The URL for all products
api_url = "https://dummyjson.com/products"
# Get category input from the user
user_category = input("Enter a product category to search for (e.g., smartphones, laptops): ").lower()
شرح هذه الجزئية:
هنا نقوم بالتحضير. user_category.lower()
تضمن تحويل مدخلات المستخدم إلى أحرف صغيرة لتسهيل المقارنة لاحقًا.
ثانياً، سنرسل الطلب ونعالج الاستجابة، مع التأكد من التعامل مع الأخطاء.
try:
response = requests.get(api_url)
response.raise_for_status() # Check for request errors
data = response.json()
all_products = data.get('products', []) # Safely get the list of products
except requests.exceptions.RequestException as e:
print(f"Could not connect to the API: {e}")
all_products = [] # If there's an error, we work with an empty list
شرح هذه الجزئية:
نستخدم try...except
للاتصال الآمن. data.get('products', [])
هي طريقة آمنة للحصول على قائمة المنتجات؛ إذا لم يكن المفتاح 'products'
موجودًا، فسنحصل على قائمة فارغة بدلاً من خطأ.
ثالثاً، سنقوم بالبحث عن المنتجات التي تطابق فئة المستخدم وعرضها.
found_products = False # A flag to check if we found any products
print(f"\nSearching for products in category: '{user_category}'...")
print("-" * 30)
if all_products:
# Loop through each product in the list
for product in all_products:
# Check if the product's category matches the user's input
if product.get('category', '').lower() == user_category:
# If it matches, print its details
print(f"Title: {product['title']}, Price: ${product['price']}")
found_products = True # Set the flag to True
# After the loop, check if any products were found
if not found_products:
print("No products found in this category.")
شرح هذه الجزئية:
نستخدم متغيرًا منطقيًا (found_products
) كعلم لتتبع ما إذا كنا قد وجدنا أي منتجات. نتكرر على قائمة all_products
، وداخل الحلقة، نقارن فئة كل منتج مع مدخلات المستخدم. إذا وجدنا تطابقًا، نطبع التفاصيل ونرفع العلم. في النهاية، إذا بقي العلم False
، فهذا يعني أننا لم نجد شيئًا، فنطبع الرسالة المناسبة.
6. خلاصة الفصل
- البيئات الافتراضية هي ممارسة أساسية لعزل اعتماديات كل مشروع ومنع التضارب.
- نستخدم وحدة
venv
لإنشاء البيئات، وactivate
لتفعيلها. pip
هي أداتك الأساسية لتثبيت وإدارة المكتبات الخارجية داخل البيئة المفعلة.- ملف
requirements.txt
ضروري لتوثيق ومشاركة اعتماديات مشروعك.
ماذا بعد؟
الآن بعد أن أصبحت قادرًا على كتابة كود منظم واستخدام أدوات خارجية قوية ضمن بيئات عمل احترافية، حان الوقت لنتعلم في الفصل الثالث عشر كيف ننظم ملفات مشروعنا نفسه بطريقة أنظف باستخدام الوحدات (Modules) والحزم (Packages).