Перейти до основного вмісту

Розуміння змін у пакетах 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, термін пакет використовується для позначення як дистрибутивів, так і пакетів — потрібно звертатися до контексту, щоб зрозуміти, що мається на увазі. Загалом: якщо ти 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, який не містив власного коду, але спричиняв встановлення всіх інших компонентів. Ми називали це метапакетом — за аналогією з подібними концепціями в інших менеджерах пакетів. Код ядра 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, аж поки починаючи з 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, і ми залишимо його найновішу версію в робочому стані, щоб старий науковий код і застарілі пакети могли й надалі легше його використовувати.

На жаль, через спадщину метапакету та недоліки pip як менеджера пакетів, ми не можемо забезпечити повністю безперебійний шлях оновлення для користувачів до Qiskit v1.0, особливо поки одні пакети залежать від ранніх версій Qiskit, а інші вимагають лише Qiskit v1.0+. Ці проблеми зменшуватимуться в міру того, як більше екосистеми переходитиме на Qiskit v1.0.

Куди поділися модулі застосунків?

Ти можеш помітити, що команда pip install qiskit більше не включає пакети на кшталт qiskit-aer або qiskit-nature. З видаленням структури метапакету багато з цих пакетів були розділені на дистрибутиви, які потрібно встановлювати окремо.

До виходу Qiskit SDK v1.0 Qiskit складався з багатьох різних дистрибутивів Python, таких як qiskit-terra — ядро компілятора; qiskit-aer — високопродуктивний симулятор; оригінальний провайдер IBM Quantum®; та кілька нині застарілих пакетів, що надавали певні експериментальні алгоритмічні функції або функції запуску експериментів.

Якщо хочеш встановити пакети, які раніше входили до метапакету Qiskit, відвідай екосистему Qiskit, щоб знайти широкий спектр пакетів на свій вибір. Також можеш прочитати посібник з міграції v1.0 для отримання додаткової інформації про те, як встановити новий дистрибутив.