فوضى التبعيات العائمة
في بيئة بايثون، تُعد عبارة "تعمل على جهازي" عرضاً شهيراً لفشل إدارة التبعيات. عندما تعتمد على قيود غير محددة الإصدار مثل
>=1.0، فإن بيئتك تخضع لتقلبات تحديثات الحزم الأصلية. قد يؤدي رفع طفيف في الإصدار إلى إدخال تغييرات كاسرة، مما يسبب أخطاء غامضة في الإنتاج يصعب إعادة إنتاجها محلياً. تُعرف هذه الظاهرة على نطاق واسع باسم "جحيم التبعيات"، وهي السبب الرئيسي في أن إمكانية إعادة الإنتاج تُعد حجر الزاوية في هندسة البرمجيات الاحترافية.
لمواجهة هذه المشكلة، تحولت المعايير الصناعية نحو ملفات القفل (lock files) — وهي لقطات ثابتة لجميع التبعيات المحلولة. وعلى الرغم من أن أدوات مثل
pip تفتقر منذ فترة طويلة إلى الدعم الأصلي لملفات القفل، فقد طورت المجتمع حلولاً قوية. يُعد Poetry و pip-tools (تحديداً
pip-compile) من أقوى الأدوات لتحقيق بناءات حتمية (deterministic). يستكشف هذا الدليل كيفية استخدام كل منهما لإنشاء بيئات بايثون قوية وقابلة لإعادة الإنتاج.
الاستراتيجية أ: النظام البيئي المتكامل لـ Poetry
يتعامل Poetry مع إدارة التبعيات باعتبارها ميزة أساسية بدلاً من كونها تفكيراً لاحقاً. يجمع بين حل التبعيات، وإدارة البيئات الافتراضية، وتعبئة الحزم في أداة واحدة. يكمن قلب هذا النظام في ملف
poetry.lock.
عند تشغيل
poetry install، لا يقوم Poetry بتثبيت الحزم المدرجة في
pyproject.toml فحسب؛ بل يقرأ ملف القفل لضمان تثبيت كل تبعية غير مباشرة (transitive dependency) على تجزئة إصدار دقيقة. يضمن هذا أن تكون البيئة على جهاز الكمبيوتر الخاص بك مطابقة تماماً للبيئة الموجودة في CI/CD والإنتاج.
إليك كيفية إعداد مشروع Poetry أساسي:
# Initialize a new project
poetry new my-project
# Add a dependency
poetry add requests
# This generates poetry.lock, pinning requests and all its sub-dependencies
لتثبيت التبعيات في بيئة الإنتاج، استخدم دائماً ملف القفل. لا تقم أبداً بتشغيل
poetry update في خط أنابيب الإنتاج، لأن ذلك سيعيد إنشاء ملف القفل بإصدارات أحدث محتملة.
# Strict installation from lock file
poetry install --no-dev
تكمن ميزة Poetry في تكاملها السلس. ومع ذلك، إذا كنت ملتزماً بسير عمل
pip القياسي أو تتطلب فصلًا صارماً بين تبعيات وقت البناء ووقت التشغيل، فقد يبدو النهج الشامل لـ Poetry ضخماً جداً.
الاستراتيجية ب: نهج pip-tools
بالنسبة للمطورين الذين يفضلون بساطة
pip ولكنهم يحتاجون إلى بناءات حتمية، فإن
pip-tools هو الحل المثالي. تأخذ أداة
pip-compile ملف
requirements.in (الذي يدرج تبعياتك المباشرة) وتحلها إلى ملف
requirements.txt مع تثبيت كامل للإصدارات.
تحاكي هذه الطريقة سلوك وحدات Go أو Cargo، مما يوفر فصلًا واضحاً بين النية (ما تريده) والتنفيذ (ما تحصل عليه).
# Create a requirements.in file
echo "requests==2.28.0" > requirements.in
# Resolve and compile dependencies
pip-compile requirements.in
# This generates a fully pinned requirements.txt
سيبدو ملف
requirements.txt المولد كما يلي:
#
# This file is autogenerated by pip-compile with python 3.10
# To update, run:
#
# pip-compile requirements.in
#
certifi==2022.12.7
charset-normalizer==2.1.1
idna==3.4
requests==2.28.0
urllib3==1.26.13
لاحظ كيف يجلب
requests إصدارات محددة من
certifi و
urllib3 وما إلى ذلك. هذا الملف آمن لإضافته إلى مستودعك وتثبيته في بيئة الإنتاج باستخدام
pip install -r requirements.txt.
اختيار الأداة المناسبة
تعمل كلتا الأداتين على حل نفس المشكلة الأساسية: إمكانية إعادة الإنتاج. يعد Poetry أكثر ملاءمة للمشاريع الجديدة (greenfield) أو الفرق التي تريد سير عمل موحد لبناء ونشر الحزم. فهو يتعامل مع البيئات الافتراضية تلقائياً ويوفر واجهة سطر أوامر غنية لإدارة السكريبتات والإضافات.
من ناحية أخرى، يعد pip-tools أخف وزناً ويتكامل بسلاسة مع ملفات Dockerfile وسير عمل CI/CD الحالية التي تستخدم بالفعل
pip. كما أنه مفضل للمشاريع التي لديها تبعيات بناء معقدة (مثل الامتدادات C) حيث قد يواجه محلل Poetry صعوبات أحياناً.
الخاتمة
لم يعد جحيم التبعيات عذراً لعدم استقرار الإنتاج. من خلال اعتماد إما
poetry.lock الخاص بـ Poetry أو
requirements.txt الخاص بـ pip-tools، تضمن أن برمجياتك تتصرف بشكل متسق عبر جميع البيئات. النقطة الرئيسية بسيطة: لا تقم أبداً بالالتزام بقيود الإصدار العائم. ثبت تبعياتك، وثق ملفات القفل، ونام براحة بال في الليل.