ماذا يغيّر انتهاء دعم Python 3.10
ينشر دليل مطوّري Python جدول كل فرع. وقد صدر Python 3.10 في أكتوبر 2021، وهو مدرج هناك بوصفه منتهي الدعم منذ 1 أكتوبر 2026. عملياً لم يعد الفرع يتلقى أي إصلاح، ولا حتى الأمني منه: أي ثغرة تُكتشف في المفسّر أو في مكتبته القياسية ستبقى مفتوحة.
يستمر الكود في العمل وتنجح الاختبارات، وهذا ما يجعل الوضع مضللاً. نهاية الدعم لا تكسر شيئاً في يومها، لكنها تسحب شبكة الأمان في كل الأيام التالية، بينما تتخلى التوزيعات والصور الأساسية والمكتبات الخارجية عنه تدريجياً.
كلفة مفسّر متجمّد
- ثغرات بلا إصلاح — كل ثغرة في المفسّر تُنشر بعد نهاية الدعم تبقى مفتوحة في فرع 3.10، ولا يغلقها إلا رفع الإصدار.
- تبعيات تبتعد — سترفع المكتبات عاجلاً أو آجلاً حدها الأدنى لإصدار Python، وينتهي التثبيت الجديد إلى حل إصدارات قديمة أو إلى الفشل.
- صور أساسية متجمّدة — صورة حاوية مبنية على فرع 3.10 تعتمد على مفسّر بلا إصلاحات من المصدر، وتشير فحوص الثغرات لديك إلى ذلك في كل عملية بناء.
- تدقيقات متعثرة — المفسّر غير المدعوم خط أحمر في المراجعات الأمنية واستبيانات الموردين لدى عملائك.
- ترقية مفروضة — من 3.10 إلى 3.12 هناك فارق إصدارين فرعيين؛ وكلما انتظرت طالت قائمة الأعطال، والمشروع المخطط له أقل كلفة من طارئ بعد حادث.
جدول دعم فروع Python
مرّر الجدول أفقيًا
| الإصدار | نهاية الدعم | ما يعنيه لخادم VPS لديك |
|---|---|---|
| 3.9 | أكتوبر 2025 | خارج الدعم منذ أكثر من سنة: غادره دون انتظار |
| 3.10 | أكتوبر 2026 | خارج الدعم منذ 1 أكتوبر: لا إصلاحات بعد الآن |
| 3.11 | أكتوبر 2027 | حد أدنى: يحل مشكلة اليوم لا مشكلة العام القادم |
| 3.12 | أكتوبر 2028 | الهدف الموصى به: سنتان من الهامش ونظام بيئي راسخ |
| 3.13 | أكتوبر 2029 | مدعوم لفترة أطول؛ اعتمده بعد التحقق من تبعياتك |
| 3.14 | أكتوبر 2030 | أحدث فرع في هذا الجدول وأبعدها نهايةً للدعم |
أي إصدار مستهدف تختار
Python 3.12 هو الهدف الذي نوصي به لتطبيق قائم: نهاية دعمه مخططة في أكتوبر 2028، أي سنتان من الهامش، وتدعمه الأطر الشائعة. أما Python 3.11 فهو حد أدنى يعيدك إلى الترقية نفسها في أكتوبر 2027.
يحظى Python 3.13 بدعم أطول، حتى أكتوبر 2029. لا نعدّه غير مناسب: هو يفترض فقط أن تنشر كل تبعية من تبعياتك حزماً لهذا الإصدار، وهذا يُتحقق منه في بيئة الاختبار لديك. تذكير من الدليل الرسمي: تواريخ الفروع التي ما زالت نشطة مخططة ويمكن تعديلها، ولا يُعدّ نهائياً إلا تاريخا 3.9 و3.10. أعد قراءة الصفحة قبل تثبيت جدولك.
معرفة المفسّر الذي يخدم الإنتاج فعلاً
الأمر python3 --version في الطرفية لا يخبرك بالمفسّر الذي يخدم التطبيق. فقد تشغّل الخدمة بيئة افتراضية أُنشئت قبل سنوات، أو Python مبنياً يدوياً، أو صورة مجمّدة في سطر FROM python:3.10.
أحصِ كل مصدر: سطر ExecStart في وحدة systemd (systemctl cat myapp)، ونتيجة /srv/myapp/venv/bin/python --version، والأمر grep -rn "FROM python" . على ملفات Dockerfile، وحقل requires-python في pyproject.toml، والإصدار المستخدم في CI. دوّن أيضاً العمال والمهام المجدولة: غالباً ما تكون لها بيئتها الخاصة وتبقى على المفسّر القديم زمناً طويلاً بعد الموقع.
المتطلبات قبل البدء
لا تحتاج هذه الترقية إلى جهاز خاص، لكنها تتطلب وصولاً كاملاً إلى الخادم ومساحة لبيئتين متجاورتين: تشغل الثانية من القرص ما تشغله الأولى، إضافةً إلى ذاكرة بناء مؤقتة إذا كانت إحدى التبعيات بلا حزمة مبنية مسبقاً.
تحتاج إلى ملف تبعيات مقفل بإصدارات دقيقة، ومجموعة اختبارات تعمل خارج الإنتاج، ونسخة احتياطية حديثة لقاعدة البيانات، وصلاحيات root لتثبيت مترجم وملفات التطوير إن اقتضت ذلك تبعياتك المترجمة. الجولة الأولى على خادم VPS للاختبار، ولو مؤقتاً، أفضل من التجربة على خادم الإنتاج.
الترقية دون انقطاع الخدمة
تجميد الوضع القائم
من البيئة الحالية، صدّر الإصدارات الدقيقة:
/srv/myapp/venv/bin/pip freeze > requirements.lock.txt. يصف هذا الملف بدقة ما يعمل اليوم، وهو نقطة رجوعك. احفظه في نظام الإصدارات قبل المتابعة.تثبيت Python 3.12 دون المساس بالنظام
الأمر
uv python install 3.12ينزّل مفسّر 3.12 تديره أداة uv، دون استبدالpython3الخاص بالتوزيعة الذي تعتمد عليه أدواتها. وإن فضلت حزم توزيعتك، فثبّت فرع 3.12 من مستودع يوفره واستخدمpython3.12 -m venv.إنشاء البيئة الثانية بجوار الأولى
الأمر
uv venv --python 3.12 /srv/myapp/venv312ينشئ البيئة الجديدة؛ وبدون uv يؤديpython3.12 -m venv /srv/myapp/venv312العمل نفسه. تواصل القديمة خدمة الحركة: لا شيء يتغير. البيئة الافتراضية لا تُنقل من مكانها، ولهذا تحمل الجديدة اسماً آخر.إعادة التثبيت من الملف المقفل
الأمر
VIRTUAL_ENV=/srv/myapp/venv312 uv pip sync requirements.lock.txtيثبّت الإصدارات المدرجة بدقة. وباستخدام pip:/srv/myapp/venv312/bin/pip install -r requirements.lock.txt. وإذا لم يوجد إصدار مثبّت لـ 3.12 أو تعذّر بناؤه، يتوقف التثبيت هنا: وهذا هو المطلوب، فتكتشف العطل قبل الإنتاج. دوّن كل حزمة تحتاج إلى رفع.إعادة تشغيل الاختبارات
شغّل الاختبارات بالمفسّر الجديد:
/srv/myapp/venv312/bin/python -m pytest، أو/srv/myapp/venv312/bin/python manage.py testمع Django مسبوقاً بـmanage.py check. اقرأ ملخص تحذيرات الإهمال: فهي تنبئ بأعطال الإصدار التالي. يجب أن تنجح الاختبارات بالمفسّرين معاً قبل المتابعة.رفع ما تعطّل فقط
دوّن الحزم المسببة، وارفعها واحدة واحدة، ثم أعد توليد الملف المقفل من البيئة الجديدة:
/srv/myapp/venv312/bin/pip freeze > requirements.312.txt. احتفظ بالقائمتين، واحدة لكل مفسّر، طوال فترة التبديل.تشغيل التطبيق بالتوازي على منفذ محلي
شغّله بالبيئة الجديدة على منفذ حر، مثلاً
/srv/myapp/venv312/bin/gunicorn myapp.wsgi --bind 127.0.0.1:8001(أوuvicornمع FastAPI). أرسل إليه طلبات حقيقية بواسطةcurl: الصفحة الرئيسية، تسجيل الدخول، عملية كتابة في قاعدة البيانات. تبقى الحركة العامة على العملية القديمة، ولا يبرر الانتقال إلى التبديل إلا نتيجة مطابقة.
التبديل والتراجع بسطر واحد
يجب ألا يغيّر التبديل سوى مسار واحد. اجعل وحدة systemd تشير إلى رابط لا إلى البيئة نفسها: ExecStart=/srv/myapp/venv-active/bin/gunicorn myapp.wsgi --bind 127.0.0.1:8000. أنشئ أولاً الرابط إلى الحالة الراهنة بالأمر ln -sfn /srv/myapp/venv /srv/myapp/venv-active، ثم systemctl daemon-reload وإعادة تشغيل لا تغيّر شيئاً.
يصبح التبديل إلى 3.12 عندئذ ln -sfn /srv/myapp/venv312 /srv/myapp/venv-active && systemctl restart myapp، ويكون التراجع هو السطر نفسه بالمسار القديم. أما التطبيق داخل حاوية فالرافعة هي الصورة الأساسية: انتقل من FROM python:3.10-slim إلى FROM python:3.12-slim، وأعد البناء بالأمر docker compose up -d --build، وتراجع بإعادة السطر السابق.
في الحالتين احتفظ بالبيئة أو الصورة القديمة أياماً، وتابع السجلات بالأمر journalctl -u myapp -f خلال الساعة الأولى.
نقاط العطل التي يجب فحصها
بين 3.10 و3.12 نادراً ما ينشأ العطل من كودك، وهو ينشأ دائماً تقريباً مما يحيط به. ثلاث عائلات تتكرر: الوحدات المحذوفة من المكتبة القياسية، والتبعيات المترجمة، والحد الأدنى لإصدار أطرك. تسرد ملاحظات إصدار Python 3.12 ما يختفي؛ اقرأها وملفك المقفل مفتوح بجانبها.
قائمة تحقق قبل التبديل
- وحدات محذوفة — يحذف Python 3.12 الوحدات
distutilsوasynchatوasyncoreوimp؛ الأمرgrep -rnE "distutils|asyncore|asynchat|import imp" .يكشف استخداماتك المباشرة، وقائمة تبعياتك تكشف غير المباشرة. - setuptools لم يعد مثبتاً مسبقاً — لا تضمّنه البيئات التي ينشئها
venvفي 3.12؛ والحزمة التي تستوردpkg_resourcesدون أن تعلنه تفشل ما لم تنفذpip install setuptools. - حزم مبنية مسبقاً — يجب أن تنشر التبعيات المترجمة (مشغلات قواعد البيانات، معالجة الصور، التشفير) حزمة لـ 3.12؛ والأمر
pip install --only-binary=:all: -r requirements.lock.txtيفشل سريعاً بدل أن يبدأ عملية بناء. - الحد الأدنى لإصدارات الأطر — لا يدعم Django 4.2 بايثون 3.12 إلا ابتداءً من 4.2.8، ويقبله Django 5.0 وما بعده؛ أما FastAPI فأعد قراءة تصنيفات Python للإصدار الدقيق الذي تثبّته.
- تحذيرات الإهمال — الدالتان
datetime.utcnow()وdatetime.utcfromtimestamp()مهملتان في 3.12؛ استبدل بهماdatetime.now(datetime.UTC)وdatetime.fromtimestamp(ts, datetime.UTC). - مكتبات النظام المشتركة — تعزل البيئة الموازية حزم Python لا مكتبات نظام التشغيل (عميل PostgreSQL مثلاً): دوّنها، فقد يغيّرها تحديث النظام من تحت قدميك.
استكشاف الأخطاء: الأعطال التي تتكرر
تظهر هذه الرسائل منذ أول تشغيل للاختبارات على Python 3.12. لكل منها سبب معروف وعلاج قصير.
الرسالة الملاحظة وعلاجها
- ModuleNotFoundError: No module named 'distutils' — غادرت الوحدة المكتبة القياسية. ثبّت
setuptoolsفي البيئة فهو ما زال يوفر نسخة منها، ثم ارفع التبعية المتسببة. - ModuleNotFoundError: No module named 'imp' — حُذفت
impوحلّت محلهاimportlib. إن جاء الاستيراد من حزمة خارجية فارفع تلك الحزمة إلى إصدار لم يعد يستخدمها. - ModuleNotFoundError: No module named 'pkg_resources' — لم يعد setuptools يُثبَّت تلقائياً في بيئات venv الخاصة بـ 3.12. الأمر
pip install setuptoolsيعيد الوحدة ريثما تستغني عنها الحزمة المتسببة. - DeprecationWarning: datetime.datetime.utcnow() is deprecated — ليس خطأ بل إشارة: استبدل الاستدعاء بكائن مدرك للمنطقة الزمنية.
- Failed building wheel for <package> — لا تملك هذه الحزمة إصداراً مبنياً مسبقاً لـ 3.12 ويحاول pip بناءها. ارفعها، أو ثبّت المترجم وملفات التطوير إن تعذّر الرفع.
ثبّت الهدف ولا تكتفِ بالترقية
اغتنم الترقية لتثبيت المفسّر بدل أن تتحمله: requires-python = ">=3.12" في pyproject.toml، ووسم صورة دقيق بدل python:3، وإصدار Python في مصفوفة CI. أضف 3.13 إلى المصفوفة بغرض المراقبة فقط: ستعرف مسبقاً هل ستكون الترقية القادمة سهلة.
جعل رفع الإصدار عادة مألوفة
ينتهي دعم فرع من Python كل عام في أكتوبر. الطريقة الموصوفة هنا (بيئة موازية، ملف مقفل، اختبارات، تبديل قابل للتراجع) لا تتعلق بإصدار بعينه: تُعاد كما هي مع 3.11 في أكتوبر 2027 ومع 3.12 في أكتوبر 2028، بحسب الجدول الحالي.
إن لم يكن تطبيقك بعد على خادم تتحكم في مفسّره، فإن دليلنا لنشر Django على VPS يغطي النشر الأول. وتتبع أدلتنا حول نهاية دعم Node.js وPHP المنطق نفسه لبقية بيئات التشغيل في أسطولك.