انتقل إلى المحتوى الرئيسي

فهم تغييرات حزم Qiskit v1.0 المُخِلَّة بالتوافق

يستخدم Qiskit v1.0 هيكلاً مختلفاً للتغليف عن إصدارات Qiskit السابقة، وهذا سيتسبب على الأرجح في مشاكل في البيئات التي تستخدم حزماً غير مستعدة لـ Qiskit v1.0.

تنبيه

لا تحاول ترقية بيئة Python افتراضية موجودة إلى Qiskit v1.0 في مكانها.

لن نُجري تغييرات تغليف مُخِلَّة بالتوافق مماثلة في المستقبل. هذا حدث لمرة واحدة فقط، عند إصدار Qiskit v1.0، وذلك تحديداً لكي تكون قصة التغليف لدينا أبسط ما يمكن في المستقبل.

تحتوي هذه الصفحة على معلومات تفصيلية حول حزمة Qiskit قبل الإصدار 1.0 وسبب إجرائنا لتغييرات التغليف المُخِلَّة بالتوافق.

نعلم أن هذا التغيير مزعج، لكنه يُعيد Qiskit إلى هيكل الحزمة البسيط الذي تستخدمه معظم حزم Python، وهو ما سيكون أسهل للمستخدمين والمطورين ومؤلفي المكتبات بعد اكتمال انتقال Qiskit v1.0.

مقدمة: قاموس مصطلحات تغليف Python

لشرح هيكل حزمة Qiskit القديمة وكيف تغيّر ذلك مع إصدار Qiskit v1.0، إليك قاموساً بالمصطلحات المتداولة في تغليف Python. الكلمات التالية لها معانٍ محددة سنستخدمها في هذا المستند.

انقر هنا لقراءة قاموس هذه الصفحة
  • module (وحدة): ملف Python واحد.

  • package (حزمة): مجلد يحتوي على __init__.py وملفات أو حزم أخرى يمكن لـ Python قراءتها. هذا هو الكود الفعلي المُثبَّت على جهازك، وهو ما يُنفَّذ عند تشغيل import something. يعتبر Python أي مجلد موجود على مسار البحث شيئاً يمكن استيراده (وسيستورد العديد من العناصر الإضافية).

    هذا ليس نفس الكائن الذي تُثبِّته بـ pip install (وهو توزيعة)، لكن عادةً ما يحمل ما تُثبِّته بـ pip install وما تستورده بـ import الاسم نفسه.

  • submodule (وحدة فرعية)، subpackage (حزمة فرعية): هذه مصطلحات غير دقيقة لكنها شائعة الاستخدام. الجزء sub يعني "موجود داخل حزمة". الوحدة الفرعية هي وحدة والحزمة الفرعية هي حزمة، لكنهما جزء من حزمة أكبر.

  • namespace package (حزمة نطاق اسمي): حزمة يمكن أن تُثبَّت فيها وحدات فرعية أو حزم فرعية من قِبَل توزيعات أخرى. والأمر الجوهري هنا أن أيًّا من التوزيعات المساهِمة في حزمة النطاق الاسمي لا تمتلك بالضرورة جميع الملفات المُثبَّتة، لذا قد يكون إلغاء تثبيتها أو ترقيتها بالكامل أمراً صعباً.

  • distribution (توزيعة): ملفات Python المضغوطة وملفات البيانات والبيانات الوصفية التي يتم تنزيلها عند تشغيل pip install something. في الغالب، تحتوي التوزيعة على حزمة واحدة بالضبط مع البيانات الوصفية حول كيفية تثبيتها (متطلباتها وما إلى ذلك)، لكن هذا ليس إلزامياً. يمكن أن تحتوي التوزيعة على صفر أو أكثر من الوحدات أو الحزم.

    إن كنت معتاداً على "مديري الحزم" خارج سياق Python، مثل apt من Debian/Ubuntu أو Homebrew على macOS، فما يُسمى فيهما "حزمة" يُسمى في Python توزيعة، ولا يوجد مقابل دقيق لما يسميه Python حزمة.

    معظم المصادر التي تتحدث عن تغليف Python تستخدم مصطلح package للدلالة على كل من التوزيعات والحزم، ويجب الرجوع إلى السياق لفهم المقصود. بشكل عام، إن كنت تستخدم import، فالمصدر يعني "حزمة"، وإن كنت تستخدم pip install، فالمصدر يعني "توزيعة".

  • search path (مسار البحث): عند محاولة تشغيل import something، يبحث Python في قائمة أماكن محددة مسبقاً عن وحدة أو حزمة باسم something. قائمة الأماكن هذه هي مسار البحث. يمكنك رؤية مسار البحث وتعديله من خلال sys.path.

  • requirement (متطلب): تحتوي التوزيعة على معلومات عن التوزيعات الأخرى التي تعتمد عليها عند تثبيتها. أي توزيعة ضرورية تُعدّ متطلباً، ويجب على مدير الحزم (عادةً pip أو conda) التأكد من تثبيت جميع المتطلبات بإصدارات متوافقة.

Python ديناميكي للغاية وقد تنشأ العديد من التعقيدات؛ على سبيل المثال، من الممكن أن وحدة أو حزمة ما لا تتوافق مع ملفات على القرص، أو أنها امتدادات مُصرَّفة.

مسار البحث ليس بحثاً في المجلدات فحسب، لكن لأغراض هذه المناقشة، فقط الملفات الموجودة على القرص ذات صلة. التعقيدات الإضافية ليست ضرورية لفهم المشاكل الموصوفة في هذا القسم، لذا يمكنك الاعتماد على النموذج الموصوف أعلاه.

هيكل Qiskit القديم

تاريخياً، كان Qiskit يتألف من العديد من توزيعات Python: qiskit-terra، النواة المُصرِّفة؛ وqiskit-aer، المحاكي عالي الأداء؛ ومزوِّد IBM Quantum® الأصلي؛ وعدة حزم باتت قديمة كانت توفر ميزات خوارزمية استكشافية أو تجريبية معينة. لتسهيل الأمر على المستخدمين، كنا نوفر أيضاً توزيعة Python تُسمى qiskit، لم تكن تحتوي على أي كود خاص بها، لكنها كانت تُسبِّب تثبيت جميع المكونات الأخرى. سمّينا هذه الـ metapackage، قياساً على مفاهيم مماثلة في مديري الحزم الآخرين. كان كود نواة Qiskit يعيش في qiskit-terra، التي تملك جذر حزمة Python qiskit. بمعنى آخر، كانت qiskit-terra تتحكم فيما يحدث عند تشغيل import qiskit. حتى Qiskit v1.0، كانت حزمة qiskit حزمة نطاق اسمي وكانت تحتوي على حزمة نطاق اسمي ثانية على المسار qiskit.providers.

هذا التنظيم سبّب لنا ولمستخدمينا كثيراً من المشاكل.

على سبيل المثال، كانت المكتبات التي تعتمد على Qiskit في أغلب الأحيان تحتاج فعلياً إلى النواة المُصرِّفة فقط، ولا تستلزم بقية النظام البيئي الكبير المُثبَّت مع pip install qiskit. وبالتالي كانت تُحدِّد متطلبها بشكل صحيح على أنه qiskit-terra. لكن عندما حاول المستخدمون إلغاء تثبيت Qiskit بتشغيل pip uninstall qiskit، واجه pip مشاكل:

  • لا يُزيل pip التوزيعات غير المستخدمة. لذا فإن pip uninstall qiskit لم يفعل شيئاً يُذكر؛ إذ لم يكن في التوزيعة أي كود، فلم يُزَل أي كود.
  • حتى لو كان سيُزيل الكود، كانت ستظل توزيعات كثيرة مُثبَّتة لأنها تعتمد على qiskit-terra.
  • حتى لو أُلغي تثبيت qiskit-terra، ربما كان لا يزال يترك مجلد qiskit قابلاً للاستيراد دون أي كود صالح للاستخدام، لأنه كان حزمة نطاق اسمي.

عند تثبيت أو ترقية التوزيعات بأمر pip install، لا يأخذ pip أيضاً في الاعتبار قرارات المتطلبات السابقة. لأنه كانت هناك حزمتان، فإن ترقية حزمة تستلزم ترقية qiskit-terra كانت تُفضي إلى بيئة غير صالحة؛ إذ كان pip يُرقِّي qiskit-terra ويترك qiskit دون تغيير. كان يُصدر تحذيراً في هذا الأمر وفي جميع أوامر pip install اللاحقة، لكن لأنه لم يظهر أي خلل، كان المستخدمون يتجاهلون التحذير عادةً، ولم يكن pip يُصدر حالة خطأ أو يمنع العمليات.

بمرور الوقت، أزلنا عناصر من حزمة qiskit الـ metapackage حتى بات ابتداءً من Qiskit v0.44 فقط qiskit-terra المتبقية. من هذه المكونات، لا تزال qiskit-aer موجودة ومُحدَّثة بنشاط، لكنها تُثبَّت الآن كتوزيعة منفصلة.

بالمثل، أوقفنا بشكل متزايد استخدام المكتبات الأخرى لخطافات النطاق الاسمي. أزلنا آخر استخدام لـ Qiskit للخطافات في الحزم غير المُهجَرة مع إصدار Qiskit Aer v0.11 وحزمة Python الجديدة qiskit_aer، وإن كنا حتى Qiskit v1.0 نُجبر مسار النطاق الاسمي qiskit.providers.aer على العمل. ابتداءً من Qiskit v1.0، أزلنا إمكانية الحزم لتوسيع أي نطاق اسمي qiskit. وبالتالي، فإن pip uninstall على التوزيعة الصحيحة في بيئة صالحة يعمل الآن كما هو متوقع.

هيكل Qiskit الجديد

ابتداءً من الإصدار 1.0، يتكون Qiskit من توزيعة واحدة تُسمى qiskit، تُثبِّت حزمة واحدة تُسمى أيضاً qiskit، تمتلك جميع الكود الموجود في مجلدها. هذا هو الهيكل الطبيعي لكود Python، وهو أبسط هيكل وأقله عرضة للأخطاء.

لن تُحدَّث توزيعة qiskit-terra على PyPI إلى الإصدار 1.0 أو ما بعده؛ إذ حلّت qiskit محلها كلياً. لم يعد اسم qiskit-terra جزءاً من عملية التثبيت. لكن حزمة qiskit-terra لن تُزال من PyPI، وسنتركها في أحدث إصدار لها في حالة عمل، حتى تتمكن الأكواد العلمية القديمة والحزم الموروثة من الاستمرار في استخدامها بسهولة أكبر.

للأسف، بسبب الإرث التاريخي للـ metapackage وقصور pip كمدير حزم، لا يمكننا توفير مسار ترقية سلس تماماً للمستخدمين نحو Qiskit v1.0، خاصةً بينما تعتمد بعض الحزم على إصدارات سابقة من Qiskit وتستلزم بعضها Qiskit v1.0+ فقط. ستتلاشى هذه المشاكل تدريجياً مع انتقال المزيد من النظام البيئي إلى Qiskit v1.0.

أين ذهبت وحدات التطبيقات؟

قد تلاحظ أن الأمر pip install qiskit لم يعد يشمل حزماً مثل qiskit-aer أو qiskit-nature. مع إزالة هيكل الـ metapackage، انقسمت كثير من هذه الحزم إلى توزيعات تحتاج إلى تثبيت منفصل.

قبل إصدار Qiskit SDK v1.0، كان Qiskit يتألف من العديد من توزيعات Python المختلفة، مثل qiskit-terra، النواة المُصرِّفة؛ وqiskit-aer، المحاكي عالي الأداء؛ ومزوِّد IBM Quantum® الأصلي؛ وعدة حزم باتت قديمة كانت توفر ميزات خوارزمية استكشافية أو تجريبية معينة.

إن أردت تثبيت الحزم التي كانت مضمَّنة سابقاً في حزمة Qiskit الـ metapackage، تفضّل بزيارة منظومة Qiskit البيئية للعثور على مجموعة من الحزم تناسب احتياجاتك. يمكنك أيضاً قراءة دليل الانتقال إلى v1.0 للمزيد من المعلومات حول كيفية تثبيت التوزيعة الجديدة.