Installing Python packages typically requires an active internet connection to download packages from a repository such as PyPI (Python Package Index). However, in situations without internet access, developers can still install Python packages offline by using various alternative methods.
Solution 1: Using Wheel Files
Wheel is a built-in binary package format used by Python allowing for faster installation without needing to build the source code. Installing packages using wheel files can be performed offline and is straightforward.
The steps:
- Download the wheel file (.whl) for the desired package from PyPI or another source using a machine with internet access.
- Transfer the wheel file to the offline target machine using a USB drive or other storage medium.
- Use the Python package installer
pip
to install the wheel file.
Example:
pip install /path/to/package_name.whl
Advantages: Quick and simple installation. Does not require building the package.
Limitations: Dependency resolution is manually done. You need to ensure all dependencies are also downloaded (maybe some time in the past).
Solution 2: Using Source Distribution Files
This method involves installing packages from a tarball containing the source code. It is more challenging but useful if wheel files are not available.
Steps:
- Download the package’s source distribution file (.tar.gz) from PyPI or other sources.
- Copy the file to the offline environment.
- Unpack the file and run the installation script.
Example:
tar xvzf package_name.tar.gz
cd package_name
python setup.py install
Advantages: Works when wheel files are not available. More control over build process.
Limitations: More complex. Requires all system dependencies to be present. Might not work for packages that cannot be compiled without internet.
Solution 3: Using Environment Export and Import
The third way is suitable if you need to replicate a complex environment. It leverages the capability to export an environment configuration and reproduce it elsewhere.
Steps:
- Create and activate a virtual environment on a machine with internet access.
- Install all required packages within this environment.
- Export the environment to a ‘requirements.txt’ file.
- Transfer the file and all downloaded packages to the target machine.
- Recreate the environment using the requirements file.
Commands to run:
python -m venv myenv
source myenv/bin/activate
pip install necessary_packages
pip freeze > requirements.txt
# Transfer requirements.txt and myenv to offline machine
python -m venv myenv
source myenv/bin/activate
pip install -r requirements.txt --no-index --find-links /path/to/offline_pkg_dir
Advantages: Effective for duplicating complex environments.
Limitations: Can be tedious for large numbers of packages. Requires accurate tracking of package dependencies.
Conclusion
Each of the offline installation methods has its own strengths and limitations, and the choice between them can be informed by the specific situation, requirements, and constraints. While using wheel files tends to be quicker and more manageable for beginners, source distribution offers more control and might be necessary when wheels are not available. Exporting and importing an environment is a robust solution for replicating existing setups but requires careful handling of dependencies. Ultimately, developers must weigh the trade-offs when working in offline environments to decide on the most practical approach to managing Python package installations.
In some cases you have to replicate a Python project on a computer without internet connection. In these cases you must not simply copy the venv folder.
Requirements for this process: the project, a memory mass storage, another computer with internet connection.
First of all, you have to to install Python on the offline machine. Now let’s go deeper into the venv replication process.
Take a look to the requirements.txt file of the project where all the dependencies are declared. Keep in mind: this file might not contain all the recursive dependencies.
Now we are going to download all the dependencies: jump into the root of the project and launch the following command (the first one for a single dependency, the second one for the entire list of requirements) from the terminal:
pip download <package-name/version>
pip download -r ./path/to/requirements.txt -d ./download/folder/
For example:
pip download itsdangerous==2.0.1
Collecting itsdangerous==2.0.1
Using cached itsdangerous-2.0.1-py3-none-any.whl (18 kB)
Saved ./itsdangerous-2.0.1-py3-none-any.whl
Successfully downloaded itsdangerous
We can see that a wheel file or a compressed package has been now downloaded with all its recursive dependencies.
Repeat this process for the packages declared in the requirements.txt file and you will have a pool of libraries, ready to be copied into the new project.
If you have downloaded all the packages is now time to create a new fresh virtual envoronment into the project in the offline computer:
python -m venv ./venv/
Copy all the python libraries downloaded into a directory inside the project and jump inside.
To install a single wheel:
pip install xyz.wheel
To install an unpacked dependency:
pip install ./my/dependency/
To install all the dependencies automatically using the requirements.txt file:
pip install -r requirements.txt --no-index --find-links file:./path/to/dependencies/folder/
If you need to download for a different platform, you should use the extra option:
--platform
Cheers
This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.
Skip to content
Бывает необходимо установить пакеты для python на машине без интернета. Способов много, я выбрал для себя один, его и использую. «Легко» и «просто» можно скачать необходимые пакеты вместе с зависимостями и установить на другой машине, если сделать следующие.
На машине с интернетом
python3 -m venv vevn source venv/bin/active pip install pip --upgrade # директория для скачивания пакетов mkdir pkg cd pkg # отдельно скачиваю последнею версию pip pip download pip # скачиваю необходимые пакеты с зависимостями pip download -r ../requirements.txt
На машине без интернета
python3 -m venv vevn source venv/bin/active # устанавливаю ранее скаченный pip (версия может быть другая) pip install pkg/pip-20.1-py2.py3-none-any.whl # установка пакетов из списка requirements.txt, пакеты должны лежать в pkg (директория) pip install --no-index --find-links pkg -r requirements.txt
Результат выполнения
# вывод консоли у меня pip install --no-index --find-links pkg -r requirements.txt Looking in links: pkg Processing ./pkg/Flask-1.1.2-py2.py3-none-any.whl Processing ./pkg/Flask_WTF-0.14.3-py2.py3-none-any.whl Processing ./pkg/et_xmlfile-1.0.1.tar.gz Processing ./pkg/openpyxl-3.0.3.tar.gz Processing ./pkg/jdcal-1.4.1-py2.py3-none-any.whl Processing ./pkg/pylint-2.5.2-py3-none-any.whl Processing ./pkg/itsdangerous-1.1.0-py2.py3-none-any.whl Processing ./pkg/Jinja2-2.11.2-py2.py3-none-any.whl Processing ./pkg/Werkzeug-1.0.1-py2.py3-none-any.whl Processing ./pkg/click-7.1.2-py2.py3-none-any.whl Processing ./pkg/WTForms-2.3.1-py2.py3-none-any.whl Processing ./pkg/mccabe-0.6.1-py2.py3-none-any.whl Processing ./pkg/isort-4.3.21-py2.py3-none-any.whl Processing ./pkg/toml-0.10.1-py2.py3-none-any.whl Processing ./pkg/astroid-2.4.1-py3-none-any.whl Processing ./pkg/MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl Processing ./pkg/typed_ast-1.4.1-cp37-cp37m-manylinux1_x86_64.whl Processing ./pkg/wrapt-1.12.1.tar.gz Processing ./pkg/lazy_object_proxy-1.4.3-cp37-cp37m-manylinux1_x86_64.whl Processing ./pkg/six-1.14.0-py2.py3-none-any.whl Could not build wheels for et-xmlfile, since package 'wheel' is not installed. Could not build wheels for openpyxl, since package 'wheel' is not installed. Could not build wheels for wrapt, since package 'wheel' is not installed. Installing collected packages: itsdangerous, MarkupSafe, Jinja2, Werkzeug, click, Flask, WTForms, Flask-WTF, et-xmlfile, jdcal, openpyxl, mccabe, isort, toml, typed-ast, wrapt, lazy-object-proxy, six, astroid, pylint Running setup.py install for et-xmlfile ... done Running setup.py install for openpyxl ... done Running setup.py install for wrapt ... done Successfully installed Flask-1.1.2 Flask-WTF-0.14.3 Jinja2-2.11.2 MarkupSafe-1.1.1 WTForms-2.3.1 Werkzeug-1.0.1 astroid-2.4.1 click-7.1.2 et-xmlfile-1.0.1 isort-4.3.21 itsdangerous-1.1.0 jdcal-1.4.1 lazy-object-proxy-1.4.3 mccabe-0.6.1 openpyxl-3.0.3 pylint-2.5.2 six-1.14.0 toml-0.10.1 typed-ast-1.4.1 wrapt-1.12.1
Мой файл requirements.txt для примера
Flask==1.1.2 Flask-WTF==0.14.3 et-xmlfile==1.0.1 openpyxl==3.0.3 jdcal==1.4.1 pylint==2.5.2
Установка из tar.gz или whl
# установка одного пакета из архива pip install ./pkg-name.tar.gz
Virtualenv — это инструмент, который позволяет создавать изолированные окружения Python. Он очень полезен при разработке проектов, так как позволяет избежать конфликтов между зависимостями различных проектов. Однако, чтобы использовать virtualenv, необходимо его установить. В этой статье мы рассмотрим подробную инструкцию по установке virtualenv без доступа к интернету.
Для установки virtualenv без интернета вам потребуется предварительно загрузить его установочный пакет. Вы можете сделать это, посетив официальный сайт virtualenv и скачав актуальную версию пакета для вашей операционной системы. Обязательно выберите пакет в формате «tar.gz» или «zip», чтобы иметь возможность установить его в оффлайн режиме.
После того, как у вас есть установочный пакет virtualenv, вы можете перейти к процессу его установки. Вам необходимо распаковать скачанный пакет в удобное место на вашем компьютере. Затем откройте командную строку или терминал и перейдите в каталог, в который вы распаковали пакет.
Далее, в командной строке или терминале, выполните следующую команду: python setup.py install. Эта команда запустит процесс установки virtualenv. В течение нескольких секунд или минут, в зависимости от скорости вашего компьютера, установка будет завершена.
Содержание
- Подготовка к установке
- Скачивание необходимого ПО
- Создание виртуальной среды
- Активация виртуальной среды
- Проверка установки
Подготовка к установке
Перед установкой virtualenv без интернета необходимо выполнить несколько подготовительных шагов.
Во-первых, убедитесь, что на вашем компьютере установлен Python версии 3 и выше. Вы можете проверить это, выполнив команду:
Если вы видите сообщение с указанием версии Python, значит, он уже установлен. В противном случае, вам необходимо установить Python с официального сайта Python (https://www.python.org).
Во-вторых, необходимо убедиться, что у вас есть доступ к пакету virtualenv. Если у вас нет доступа к интернету, вы можете заранее скачать пакет virtualenv и сохранить его на своем компьютере или на устройстве с доступом к интернету.
После скачивания пакета virtualenv, скопируйте его на компьютер, на котором вы планируете установить virtualenv.
Теперь, когда у вас есть установленный Python и пакет virtualenv, вы готовы перейти к установке virtualenv без интернета. Следуйте инструкциям по установке, описанным в данной статье.
Скачивание необходимого ПО
Прежде чем начать устанавливать virtualenv без доступа к Интернету, вам потребуется скачать несколько файлов.
- Python: Перейдите на официальный сайт Python (https://www.python.org/), найдите раздел «Downloads» и выберите последнюю стабильную версию Python. Скачайте установочный файл для вашей операционной системы.
- Pip: Перейдите на официальный сайт Pip (https://pip.pypa.io/en/stable/installing/), скачайте скрипт установки get-pip.py и сохраните его локально.
- Virtualenv: Перейдите на официальный сайт Virtualenv (https://virtualenv.pypa.io/en/latest/installation.html), найдите раздел «Installing without pip» и скачайте исходный код пакета.
После завершения скачивания всех необходимых файлов, вы будете готовы к установке virtualenv в оффлайн-режиме.
Создание виртуальной среды
Процесс создания виртуальной среды позволяет изолировать проект от системных зависимостей и установленных пакетов.
- Перейдите в директорию проекта с помощью команды
cd path/to/project
, гдеpath/to/project
— путь к папке с вашим проектом. - Введите команду
python -m venv venv
, гдеvenv
— название виртуальной среды (может быть любым). - Активируйте виртуальную среду с помощью команды:
- для операционной системы Windows:
venv\Scripts\activate
- для операционной системы macOS/Linux:
source venv/bin/activate
После выполнения этих шагов вы будете находиться внутри виртуальной среды и сможете устанавливать пакеты, не влияя на глобальные настройки вашей системы.
Активация виртуальной среды
После установки и создания виртуальной среды можно ее активировать для работы с проектом. Активация виртуальной среды позволяет изолировать проект от других установленных пакетов и версий Python.
Выполните следующую команду в командной строке, чтобы активировать виртуальную среду:
Операционная система | Команда активации |
---|---|
Windows | .\venv\Scripts\activate |
Unix/OS X | source venv/bin/activate |
После выполнения команды вы увидите, что командная строка изменилась, и теперь перед именем пользователя отображается имя активированной виртуальной среды в круглых скобках.
Теперь вы можете устанавливать и использовать пакеты внутри виртуальной среды, и любые изменения, сделанные в проекте, будут ограничены только этой средой.
Проверка установки
После завершения установки Virtualenv вам необходимо убедиться в том, что он работает корректно. Для этого выполните следующие шаги:
- Откройте командную строку.
- Введите команду
virtualenv --version
и нажмите Enter.
Если в результате вы получите версию установленного Virtualenv, значит он успешно установлен и готов к использованию. Если же вы получите сообщение об ошибке или команда не будет распознана, возможно, вам потребуется повторить установку и проверить корректность выполнения всех предыдущих шагов.
Также вы можете проверить, что Virtualenv работает правильно, создав новое виртуальное окружение и активируя его. Для этого выполните следующие команды:
# | Команда | Описание |
---|---|---|
1 | virtualenv myenv |
Создает новое виртуальное окружение с именем myenv. |
2 | source myenv/bin/activate |
Активирует созданное виртуальное окружение. |
3 | python --version |
Если после выполнения последней команды вы увидите версию Python, это будет означать, что Virtualenv работает корректно и вы готовы к использованию виртуальных окружений в своих проектах.
Хочешь понять — объясни другому
(с) Джейсон Стэтхем
Предисловие
Разговор в этой статье пойдет о том, как достать пакеты Python для оффлайн установки на разных платформах и разных версиях Python. Возможно я плохо искал, но на просторах интернета я не смог найти достаточное количество статей на русском языке, которые бы подробно объясняли, как производить загрузку пакетов и дальнейшую их доставку на машины с разными платформами и версиями языка.
Периодически возникают ситуации или необходимость запуска Python на машинах, которые не имеют доступа к интернету. Зачастую такая необходимость может возникнуть по двум причинам:
-
в случае если машина находится территориально там, где доступ к сети невозможен, в удаленных и малонаселенных районах;
-
когда по тем или иным причинам целевая машина изолирована от внешних сетей (требования безопасности и т.д.).
Тогда старательный разработчик идёт туда где есть интернет, на этой машине производит загрузку необходимых пакетов, записывает их на носитель и несёт всё это дело обратно для установки на целевой платформе. В принципе, звучит не так страшно. Давайте потянем за ниточку и быстро решим все проблемы …
И в самом деле, будет всё просто, в случае если компьютер на котором вы загружаете пакеты будет иметь аналогичную операционную систему и версию Python, тем что и на целевой машине. Также проблем не будет если вы загружаете один какой-нибудь маленький пакет, у которого минимальное количество зависимостей.
Но мир начинает играть совсем другими красками, когда у вас между целевой машиной и той, на которой вы производите загрузку имеются отличия и в операционной системе и в версии Python, а набор зависимостей между пакетами начинает зашкаливать.
В статье я постараюсь разобрать три основных варианта:
-
Операционная система и версия Python на целевой машине и машине для загрузки пакетов совпадают
-
Версия Python на целевой машине и машине для загрузки совпадают но операционные системы разные
-
На целевой машине и машине для загрузки пакетов отличаются и операционная система и версия Python
Немного теории
И прежде чем приступить к разбору этих вариантов, сначала я хочу описать основные параметры с которыми нам придётся столкнуться в статье.
Алгоритм работы загрузчика pip можно посмотреть на странице документации. Общий очень упрощенный синтаксис такой:
pip download [options] package_name
основные опции, с которыми встретимся далее:
-
—requirement, -r — использовать список зависимостей
-
—only-binary — не используйте пакеты с исходным кодом.
-
—dest, -d — адрес директории для загрузки пакетов
-
—platform — версия операционной системы
-
—python-version — версия python
-
—implementation — реализация python
Что для нас будет важно. Важно будет понять, как обозначить версию операционной системы, как обозначить версию Python, как обозначить вид пакета, который нам необходимо будет загрузить. Дальше я постараюсь привести пример таблицв в которой будут указаны параметры
Код параметра |
Значение параметра |
Операционные системы [—platform] |
|
win_amd64 |
Любой windows 64 разряда |
win32 |
Любой windows 32 разряда |
muslinux_1_1_x86_64 |
Alpine linux 32 64 разряда |
muslinux_1_1_aarchh64 |
Alpine linux 64 разряда |
manylinux2014_x86_64 |
Основной дистрибутив Linux 32 64 разряда |
manylinux2014_aarch64 |
Основной дистрибутив Linux 64 разряда |
manylinux_2_17_x86_64 |
псевдоним для manylinux2014_x86_64 |
manylinux_2_17_aarch64 |
псевдоним для manylinux2014_aarch64 |
macosx_11_0_arm64 |
macOS 11 64 разряда |
macosx_10_9_x86_64 |
macOS 10 32 64 разряда |
Реализация Python [—implementation] |
|
py |
Используем ‘py’ когда пакет не зависит от реализации |
cp |
Cpython |
ip |
Iron python |
jp |
Jpython |
pp |
PyPy |
Версии Python [—python-version] |
|
312 |
Python 3.12 используйте только для мажорно-минорной версии |
38 |
Python 3.8 используйте только для мажорно-минорной версии |
37 |
Python 3.7.0 используйте только для мажорно-минорной версии |
3.7 |
Python 3.7.0 |
3.7.3 |
Python 3.7.3 |
Вот здесь про реализацию python.
Ещё давайте посмотрим какие предельные версии Python могут быть использованы операционной системой Windows.
Windows |
|
Upper Windows 7 |
Python 3.12, максимальный на дату статьи |
Windows 7 |
Python 3.8 |
Windows XP |
Python 3.4.4 |
Основные вводные мы разобрали. Теперь давайте перейдём непосредственно к задачам.
Мы с вами можем попробовать загрузить какой-нибудь простой пакет с минимальным количеством зависимостей и в данном случае конечно же проблемы возникают реже.
Если же мы с вами попытаемся загрузить пакет, у которого большое количество зависимостей — вот здесь-то мы столкнёмся со всем многообразием возможных проблем. Поэтому в качестве эксперимента будем использовать пакет label-studio. У него большое количество различных зависимостей. В том числе, там присутствуют необычные пакеты, которые просто так не загрузить из командной строки.
1. Вариант — Всё одинаково
Вероятно, это самая простая задача. В данном случае достаточно на машине, в которой есть выход в Интернет ввести код загрузки пакета:
mkdir load_packages
pip download -d load_packages label-studio
При этом, в коде загрузки у нас будут отсутствовать какие-то дополнительные параметры, кроме адреса куда скачивать файлы. Конечно, мы можем их ввести, но необходимости в данном случае нет.
Пакеты загрузятся в целевую папку. Этоти пакеты в дальнейшем можно будет использовать для установки на машине в которой выход в Интернет отсутствует.
Для установки откройте виртуальное окружение, где вы хотите установить пакет, укажите в параметрах ссылку на директорию куда перенесли ранее скачанные файлы и название пакета установки.
pip install --no-index --find-links /dir/where/your/package/lives label-studio
Что в данном случае радует, то что мы получим пакет в полном объёме со всеми зависимостями необходимыми для его установки и нам не нужно будет делать каких-то дополнительных действий. Мы получим весь объём необходимых данных всего лишь одной командой — это просто чудо!
2. Вариант — Отличаются только операционной системы
Здесь мы как обычно берём бубен и начинаем плясать. Давайте представим что у нас есть две машины:
-
целевая машина на которой нам нужно установить пакеты это Windows 7 x 64 разряда и Python 3.8
-
машина на которой у нас с вами есть выход в Интернет — это Debian 11 core 6.7.10 x 64 разряда и Python 3.8
Если вы попытаетесь повторить предыдущий вариант загрузки, то вы конечно же получите и загрузите пакеты. Только эти пакеты будут доступны для установки только на Linux. Давайте посмотрим что получилось
mkdir load_packages
pip download -d load_packages label-studio
Обратите внимание, что часть пакетов имеют версию платформы «manylinux2014_x86_64» — для Windows такое не подойдёт.
Collecting pydantic<=1.11.0,>=1.7.3
Downloading pydantic-1.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.1 MB)
|████████████████████████████████| 3.1 MB 9.6 MB/s
Collecting pyyaml>=6.0.0
Downloading PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (705 kB)
Тогда мы приступаем к вводу дополнительных параметров отвечающих за операционную систему. Как мы уже видели в таблице приведённой выше за это отвечает параметр —platform и в данном случае для того чтобы нам загрузить пакеты Windows мы будем использовать значение win_amd64. Отлично код вроде бы ввели попробуем теперь запустить.
pip download --platform win_amd64 label-studio
Итак мы встретились с первой ошибкой, что просто так параметр —platform не работает от нас требуется ввести ещё что-то.
ERROR: When restricting platform and interpreter constraints using --python-version, --platform, --abi, or --implementation, either --no-deps must be set, or --only-binary=:all: must be set and --no-binary must not be set (or must be set to :none:).
Давайте послушаемся программу и добавим новый параметр —only-binary
pip download --only-binary=:all: --platform win_amd64 label-studio
Ну не может же быть все так просто:
ERROR: Cannot install label-studio==0.4.1, label-studio==0.4.2, label-studio==0.4.3, label-studio==0.4.4, label-studio==0.4.4.post1, label-studio==0.4.4.post2, label-studio==0.4.5, label-studio==0.4.6, label-studio==0.4.6.post1, label-studio==0.4.6.post2, label-studio==0.4.7, label-studio==0.4.8, label-studio==0.5.0, label-studio==0.5.1, label-studio==0.6.0, label-studio==0.6.1, label-studio==0.7.0, label-studio==0.7.1, label-studio==0.7.2, label-studio==0.7.3, label-studio==0.7.4, label-studio==0.7.4.post0, label-studio==0.7.4.post1, label-studio==0.7.5.post1, label-studio==0.7.5.post2, label-studio==0.8.0, label-studio==0.8.0.post0, label-studio==0.8.1, label-studio==0.8.1.post0, label-studio==0.8.2, label-studio==0.8.2.post0, label-studio==1.0.0, label-studio==1.0.0.post0, label-studio==1.0.0.post1, label-studio==1.0.0.post2, label-studio==1.0.0.post3, label-studio==1.0.1, label-studio==1.0.2, label-studio==1.0.2.post0, label-studio==1.1.0, label-studio==1.1.1, label-studio==1.10.0, label-studio==1.10.0.post0, label-studio==1.10.1, label-studio==1.11.0, label-studio==1.2, label-studio==1.3, label-studio==1.3.post0, label-studio==1.3.post1, label-studio==1.4, label-studio==1.4.1.post1, label-studio==1.5.0, label-studio==1.5.0.post0, label-studio==1.6.0, label-studio==1.7.0, label-studio==1.7.1, label-studio==1.7.2, label-studio==1.7.3, label-studio==1.8.0, label-studio==1.8.1, label-studio==1.8.2, label-studio==1.8.2.post0, label-studio==1.8.2.post1, label-studio==1.9.0, label-studio==1.9.1, label-studio==1.9.1.post0, label-studio==1.9.2 and label-studio==1.9.2.post0 because these package versions have conflicting dependencies.
Какая-то проблема с зависимостями. Давайте укажем на всякий случай нашу версию Python
pip download --only-binary=:all: --python-version 38 --platform win_amd64 -d import/ label-studio==1.11.0
Что-то новенькое
ERROR: Could not find a version that satisfies the requirement drf-flex-fields==0.9.5 (from label-studio) (from versions: none)
ERROR: No matching distribution found for drf-flex-fields==0.9.5
Думали что всё получится, а тут хлоп и опять ошибка. Оказывается что из списка зависимости не все пакеты могут быть доставлены нам в виде бинарных файлов, либо не удовлетворяет требованиям нашей платформы.
Например пакет drf-flex-fields вот скрин с его странички.
Здесь доступно для скачивания только исходники в архиве.
Давайте попробуем использовать параметр —prefer-binary
ERROR: When restricting platform and interpreter constraints using --python-version, --platform, --abi, or --implementation, either --no-deps must be set, or --only-binary=:all: must be set and --no-binary must not be set (or must be set to :none:).
Ух ты Замкнутый круг! Уже знакомая ошибка — данный параметр невозможно использовать в случае если вы указываете платформу для которой предполагается установка пакетов. Вот что говорит StackOverflow.
В данном случае я сделал для себя вывод (возможно абсолютно неверный) -что мы не можем при указании платформы и версии языка закачивать не бинарные файлы.
В какой-то момент я подумал, что это действительно безвыходная ситуация. И что в момент загрузки пакетов мы рано или поздно просто остановимся на каком-то одном из пакетов из списка зависимости и дальше не пойдём. При этом полный список зависимостей нам пока что будет недоступен.
Не сдаваться — наше всё
Мне показалось правильным распилить эту задачу на несколько вариантов
-
сначала попробовать закачать те пакеты, которые имеют бинарный вариант с помощью стандартной команды pip download .
-
далее пакеты, которые не загрузились и вышла ошибка попробовать загрузить либо вручную, либо сделать какой-то автоматический обработчик, который поможет мне их получить.
Теперь возникает вопрос о полном списке зависимостей пакетов, которые мне необходимы. Где же мне его взять. Вероятно существует какие-то умные и действительно правильные способы получение полного списка зависимостей, но я до него пока что ещё не дошёл — я пошёл простым прямым квадратным перпендикулярным способом.
Сейчас у нас ситуация, когда у нас отличаются только версии операционной системы при этом версия Python у нас одна и та же. В нашем случае — 3.8 и на Windows и на Linux. Что же, теперь я попробую установить целевой пакет Label Studio на машину, в которой есть выход в Интернет. Когда все пакеты установились я использую команду
pip freeze > requirements.txt
с помощью неё я получу список всех установленных пакетов с указанием необходимых версий. Все данные запишу в файл requirements.txt.
Таким образом у меня получилось добыть список всех зависимостей. Здорово! Ну что же дальше. Ведь если мы запускаем код загрузки, то в момент когда терминал получает ошибку — он останавливается. Давайте попробуем написать некий bash скрипт, который простым перебором будет пытаться с помощью команды pip download закачивать поочередно каждый пакет из списка зависимостей. А все пакеты, по которым у нас с вами произошла ошибка, он будет записывать в текстовый файл error.txt
#!/bin/bash
mkdir packages
cat requirements.txt | while read line
do
error_output=$(pip download -d ./packages --platform win_amd64 --python-version 38 --only-binary=:all: --implementation cp "$line" 2>&1)
if [[ $error_output =~ "ERROR" ]]; then
echo "${line}"
echo "${line}" >> "error.txt"
fi
done
Отлично! У нас получилось загрузить все пакеты, которые имеют бинарный вид и получить список всех пакетов, по которым бинарный вид отсутствует. При этом мы знаем не только наименование пакета, но что нас больше всего может радовать ещё и его версию.
Теперь чтобы получить недостающие пакеты, в принципе, мы можем пойти простым человеческим путём — зайти на сайт pip.org, найти соответствующий пакет, найти его версию нажать кнопку загрузить. Ну и в принципе, таким образом мы его получим.
С учетом того, что таких ошибочных пакетов у нас небольшое количество — в принципе много времени это не займёт. Но мне стало интересно — а могу ли я автоматизировать и этот процесс. Как оказалось не всё потеряно. Давайте посмотрим с вами на структуру адреса страницы загрузкой пакета drf-flex-fields необходимой версии.
https://pypi.org/project/drf-flex-fields/0.9.5/#files
Мы видим что в адресе страницы присутствуют и наименование пакета и его версия. Таким образом, вероятно, мы сможем автоматически попасть и сформировать себе адреса страниц на которых присутствуют необходимые нам пакеты, а затем каким-то образом спарсить оттуда необходимый нам данные. Чтобы не углубляться в теорию ниже я приведу код Python скрипта который позволит нам это сделать. Назовем его — load_packages.py
import requests
from bs4 import BeautifulSoup
from tqdm import tqdm
# читаем файл с ошибками, формируем список пакетов для загрузки
with open('error.txt', 'r') as err_file:
packages = err_file.readlines()
# функции отправляет запрос на страницу загрузки пакета
def get_request(url: str) -> requests.Response:
try:
return requests.get(url)
except:
print('Request error')
return False
def load_package(package: str) -> None:
# извлекаем необходимые данные о пакете
pack_name, version = package.replace('\n', '').split('==')
# готовим адрес страницы с файлами загрузки и получаем ответ на запрос
url = f'https://pypi.org/project/{pack_name}/{version}/#files'
r = get_request(url)
# убеждаемся, что запрос не пустой
if not r:
return False
# создаём объект bs для дальнейшей обработки
soup = BeautifulSoup(r.text)
# ищем блок div с характерным классом
for element in soup.find_all("div", {"class": "card file__card"}):
# ищем tag <a href...
for tag in element:
if tag.name == 'a':
# пропускаем ссылку на загрузки хешей
if tag.text == 'view hashes':
continue
# очищаем текст от лишних знаков
text = tag.text.replace(' ', '').replace('\n', '')
# преобразуем текст а список
body = text.split('.')
# последний элемент списка это разрешение файла выбираем .gz
if body[-1] != 'gz':
continue
# получаем адрес для скачивания
url = tag.attrs['href']
try:
packet = requests.get(url)
except:
print('Load request error')
continue
# полученные байты записываем в файл
with open(f'packages/{text}', 'wb') as handle:
for data in tqdm(packet.iter_content()):
handle.write(data)
msg = f'Load package {pack_name}, ver. {version}, to file {text}'
print(msg)
for package in packages:
if package == '\n':
continue
print(f'Start load package {package}')
load_package(package)
А теперь я немножко объясню что здесь происходит. Для того чтобы, в будущем в случае каких-то изменений на сайте pip.org или ещё каких-то вещей и ошибок мы могли бы скорректировать код этого скрипта. Основная идея заключается в том, чтобы использую библиотеку request получать данные со страницы загрузки файлов. Далее с помощью пакета Beautifulsoup4 получить информацию из необходимого блока div b вычленить ссылку с пакетом архива, который имеет разрешение «.gz», скачать данные и записать файл из бинарных данных к себе в целевую папку.
Вот так выглядит страница для загрузки необходимого пакета. Так видит эту страницу человек.
А так эту страницу видит машина
В примере я привёл только кусок необходимого блока для загрузки. Здесь мы видим атрибуты блока div по которому мы сможем отфильтровать необходимый нам блок и дальше мы видим, что помимо самих пакетов ещё доступны для скачивания хэши. Соответственно в коде мы это отсеиваем. Из доступных к скачиванию пакетов мы выбираем тот, который имеет архив «.gz». Собственно Вот и вся логика работы скрипта.
Далее мы немножечко улучшим наш Баш скрипт для того, чтобы нам автоматически развернуть виртуальную среду, в которую мы установим необходимые пакеты resquest и Beautifulsoup4. Запустим саму виртуальную среду и запустим наш python скрипт.
#!/bin/bash
mkdir packages
cat requirements.txt | while read line
do
error_output=$(pip download -d ./packages --platform win_amd64 --python-version 38 --implementation cp --only-binary=:all: --implementation cp "$line" 2>&1)
if [[ $error_output =~ "ERROR" ]]; then
echo "${line}"
echo "${line}" >> "error.txt"
fi
done
python -m venv venv
source venv/bin/activate
pip install requests
pip install beautifulsoup4
pip install tqdm
python load_packages.py
В результате запуска Bash скрипта мы выполним два действия:
-
сначала закачается доступные файлы в бинарном виде запишутся ошибки по незагруженным файлам
-
далее python script прочитает наименование пакетов с ошибками и попытается загрузить их непосредственно со страницы pip.org
На примере пакета label-studio Windows 7 + python 3.8 данная задача была решена.
3. Вариант — Отличается всё
Давайте теперь задачу усложним ещё на один порядок. Представим что у нас:
-
целевая машина на которую необходимо загрузить пакеты — это Windows 7 + Python 3.8
-
машина на которой есть интернет Astra Linux common edition + Python 3.5
В данном случае у нас возникает проблема с получением полного списка зависимостей. Если мы просто поставим с вами пакет Label Studio на Python 3.5, то мы с вами получим зависимости только для Python 3.5. А в нашем конкретном случае мы вообще ничего не получим — потому что label-studio на Python 3.5, в принципе не устанавливается.
Что же тогда делать. Самый простой вариант в данном случае — это попробовать установить на вашу машину c интернетом pyenv (статья Хабр, GIT исходник).
С помощью него выбрать необходимую версию Python и далее пройти по шагам, которые представлены в пункте два.
Обратите внимание, что на старых версиях ОС необходимо указывать python3 или pip3 для вызова Python 3.хх
#!/bin/bash
mkdir packages
cat requirements.txt | while read line
do
error_output=$(pip3 download -d ./packages --platform win_amd64 --python-version 38 --implementation cp --only-binary=:all: --implementation cp "$line" 2>&1)
if [[ $error_output =~ "ERROR" ]]; then
echo "${line}"
echo "${line}" >> "error.txt"
fi
done
python3 -m venv venv
source venv/bin/activate
pip install requests
pip install beautifulsoup4
pip install tqdm
python load_packages.py
Вполне возможно, может так случиться, что pyenv не позволит установить более старшие версии языка на слабой машине или могут возникнуть какие-то иные проблемы — для этих проблем я решение, к сожалению, не нашёл.
В данном случае, вероятно, единственный выход — иметь машину, которая имеет доступ к интернету с возможностью установки на ней максимальных версий Python. Тогда pyenv вам однозначно позволит работать с версиями Python на понижение.
Или развивать легкоатлетические навыки и бегать с пакетами приложений из кабинета в кабинет. Сначала туда ->
А потом обратно <-
Вывод
Не претендую на мастерство — я не профессиональный разработчик и к этой статье я шел долго. Несколько лет бегал, как мужик на картинке выше. Когда же встретился с label-studio — я устал. Попробовал автоматизировать свою работу. И на фоне дефицита подобной информации на русском решил рассказать о своих приключениях
Будет замечательно, если настоящие профессионалы укажут на мои ошибки и подскажут верный путь. Заранее спасибо!
Ещё есть мысль в будущем, каким-то образом постараться добывать список зависимостей автоматически — для каждого пакета, без необходимой установки на текущую машину с интернетом.
Но мне почему-то кажется, что это достаточно сложная задача, с которой пытались справиться большое количество разработчиков — в результате которых, появились такие замечательные решения как poetry, uv и подобные им пакеты управления зависимостями
К картинкам приложили руки моя доча, Шедеврум и Midjourney