Что вы должны знать о виртуальных средах Python и управлении пакетами

Python

обо мне
Небольшой программист в мире программирования, в настоящее время работает руководителем команды в предпринимательской команде.Стек технологий включает Android, Python, Java и Go, который также является основным стеком технологий нашей команды. Контакт: hylinux1024@gmail.com

PythonПри большом количестве сторонних библиотек также очень удобно ссылаться на эти библиотеки, черезpip installВы можете установить эти сторонние библиотеки локальноPythonкаталог файлов библиотеки, то вы можетеimportВ проекте значительно улучшена эффективность кодирования разработчиков.
Но это также поднимает проблему: когдаAпредметы иBПроекты упоминаются одновременноLibбиблиотека, покаAпотребности проектаLibверсия 1.0,Bпотребности проектаLibВерсия 2.0.это используетpip installкоманда будетLibПрямая установка в локальную глобальную среду вызовет конфликты, которые могут вызватьAа такжеBОперационная среда не может быть удовлетворена одновременно, и операция завершается ошибкой.

Итак, виртуальная среда (virtualenv) появляется. Его основная идея заключается вОбеспечьте отдельную среду выполнения для каждого проекта, чтобы разные зависимости проекта не конфликтовали.

0x00 использовать venv+pip

1. Создать Венв

Установка виртуальной среды также очень проста, вы можете использоватьvenvмодули, например, в каталоге проекта, используяPython3Создайте виртуальную среду

 ➜ python3 -m venv venv

Итак, в каталоге проекта есть еще одинvenvфайловый каталог. Этот каталог является виртуальной средой для проекта.

Чтобы использовать виртуальную среду, ее необходимо активировать

 ➜ source venv/bin/activate

Тогда в командной строке появится

(venv) ➜  

Указывает, что виртуальная среда активирована.

Чтобы отменить виртуальную среду, используйте

(venv) ➜ deactivate

2. Используйте pip для установки/удаления

После активации виртуальной среды ее можно использоватьpipКоманда устанавливает зависимые библиотеки проекта. Например

(venv) ➜ pip install requests

pipбудетrequestsустановить наvenv/lib/python3.7/site-packagesв каталоге.

Удаление зависимых библиотек

(venv) ➜ pip uninstall requests

3. список пунктов

СмотретьvenvКакие зависимости установлены в

(venv) ➜ pip list
Package        Version 
-------------- --------
beautifulsoup4 4.7.1   
certifi        2019.3.9
requests        2.21.0    

4. заморозка пипсов

использоватьpip freezeВы можете сохранить список зависимых библиотек вrequirements.txtфайл, который позволяет участникам других проектов быстро создавать среду выполнения проекта.

(venv) ➜ pip freeze > requirements.txt

Итак, вам нужно установить зависимости проекта

(venv) ➜ pip install -r requirements.txt

Таким образом, может быть создана единая операционная среда.

5. Проблемы со схемой venv+pip

Пока все работает нормально, это должно быть хорошим решением. На самом деле, я использовал это решение все время и не сталкивался с какими-либо проблемами.
до одного дняНекоторые говорят использоватьvenv+pipЯ также не могу гарантировать согласованность и надежность моей операционной среды.. Его причина также очень проста, библиотечная среда проекта зависит отrequirements.txt,а такжеrequirements.txtИмеет ли библиотека указанный номер версии, чтобы она использоваласьpip install -r requirements.txtЭто также приведет к установке неопределенной версии.

Например

beautifulsoup4  
certifi        
requests        

Конечно, это можно решить, указав точный номер версии для каждой библиотеки, поэтому

beautifulsoup4 4.7.1   
certifi        2019.3.9
requests        2.21.0 

Это решает указанную выше проблему, но если сторонняя библиотека исправляет уязвимость, используйтеpip install --upgradeНе так-то просто обновить эти зависимые библиотеки.

еще есть вопросrequirements.txtТакже могут быть конфликты номеров версий в зависимых библиотеках.Ситуация такова:

ALib -> sublib_1.0
BLib -> sublib_2.1

ALibа такжеBLibтакже зависит отsublib, но они зависят от разных версий и в итоге используютсяpip install -r requirements.txtтакже можетНе удается запустить проект из-за несовместимости версий зависимых библиотек в зависимой библиотеке.

Так оно и появилосьpipenv

0x01 pipenv

Честно говоря, я использовалvenv+pip, увидев вопрос выше, думаю, надо понятьpipenv.

1,Установитьpipenv

➜ pip install pipenv

Два файла ссылаются после завершения установки,Pipfileа такжеPipfile.lock. Первый используется для заменыrequirements.txtфайл, последний используется для обеспечения детерминированности и непротиворечивости зависимых библиотек.

По факту,pipenvНижний уровень команды также инкапсулированpipа такжеvenvоперации и предоставляет набор простых интерактивных команд.

Создайте виртуальную среду

в каталоге проекта (например,pipenvdemo)использовать

➜ pipenv shell

Когда появится сообщение, похожее на следующее, виртуальная среда создана и активирована успешно.Конечно, вы также можете использовать--twoили--threeпараметр, указанный для использованияPython2все ещеPython3для создания можно также использовать детерминированныйPythonномер версии, например--python3.7

➜ pipenv shell --three

➜ pipenv shell --python3.7

Потому что мой компьютер локальныйPythonСреда 3.7, поэтому здесь по умолчанию будет указываться локальная версия по умолчанию.

Creating a virtualenv for this project…
Pipfile: /Users/mac/PycharmProjects/pipenvdemo/Pipfile
Using /usr/local/opt/python/bin/python3.7 (3.7.3) to create virtualenv…
⠋ Creating virtual environment...Already using interpreter /usr/local/opt/python/bin/python3.7
Using base prefix '/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7'
New python executable in /Users/mac/.local/share/virtualenvs/pipenvdemo-fHPp2Wq9/bin/python3.7
Also creating executable in /Users/mac/.local/share/virtualenvs/pipenvdemo-fHPp2Wq9/bin/python
Installing setuptools, pip, wheel...
done.

✔ Successfully created virtual environment!
Virtualenv location: /Users/mac/.local/share/virtualenvs/pipenvdemo-fHPp2Wq9
Creating a Pipfile for this project…
Launching subshell in virtual environment…
 . /Users/mac/.local/share/virtualenvs/pipenvdemo-fHPp2Wq9/bin/activate

Также в каталоге проекта (например,pipenvdemo) генерируетPipfileдокумент. Точно так же в командной строке появятся следующие стили

(pipenvdemo) ➜ pipenvdemo

вPipfileСодержание

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]

[requires]
python_version = "3.7"

2. установка пайпэнв

Если вы хотите установить стороннюю библиотеку, используйте ее напрямуюpipenv installкоманда, указанная нижеflaskномер версии для установки.

➜ pipenv install flask==1.0.1

Также можно не указывать номер версии

➜ pipenv install flask

В терминале появится сообщение, подобное следующему

Installing flask==1.0.1…
Adding flask to Pipfile's [packages]…
✔ Installation Succeeded
Pipfile.lock not found, creating…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
⠙ Locking...

также можно использовать--devПараметры используются для установки библиотек, от которых зависит среда разработки.

➜ pipenv install pytest --dev

Другой файл создается в каталоге проектаPipfile.lock,а такжеPipfileФайл также будет обновлен

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]
pytest = "*"

[packages]
flask = "==1.0.1"

[requires]
python_version = "3.7"

видеть в[packages]Зависимые библиотеки перечислены под тегамиflaskи номер версии, на нем есть еще один[dev-packages]Он используется для обозначения версии разработки зависимой библиотеки, которую можно использовать для отличия рабочей среды от среды разработки. используется только в команде--devпараметры будут установлены[dev-packages]Зависимости перечислены ниже.

Pipfile.lockСодержимое файла должно быть богаче, в основномСодержит номера версий и файлы зависимых библиотек (включая зависимые библиотеки).hashинформации, так что зависимая библиотека может быть гарантированно детерминирована.

{
    "_meta": {
        "hash": {
            "sha256": "3bba1f1c4de8dd6f8d132dda17cd3c720372a1eed94b9523b9c23013e951c8ae"
        },
        "pipfile-spec": 6,
        "requires": {
            "python_version": "3.7"
        },
        "sources": [
            {
                "name": "pypi",
                "url": "https://pypi.org/simple",
                "verify_ssl": true
            }
        ]
    },
    "default": {
        "click": {
            "hashes": [
                "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13",
                "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"
            ],
            "version": "==7.0"
        },
        "flask": {
            "hashes": [
                "sha256:cfc15b45622f9cfee6b5803723070fd0f489b3bd662179195e702cb95fd924c8",
                "sha256:dbe2a9f539f4d0fe26fa44c08d6e556e2a4a4dd3a3fb0550f39954cf57571363"
            ],
            "index": "pypi",
            "version": "==1.0.1"
        },
        "itsdangerous": {
            "hashes": [
                "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19",
                "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"
            ],
            "version": "==1.1.0"
        },
        "jinja2": {
            "hashes": [
                "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013",
                "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"
            ],
            "version": "==2.10.1"
        },
        "markupsafe": {
            "hashes": [
                "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
                "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
                "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
                "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
                "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
                "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
                "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
                "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
                "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
                "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
                "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
                "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
                "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
                "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
                "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
                "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
                "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
                "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
                "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
                "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
                "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
                "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
                "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
                "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
                "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
                "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
                "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
                "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"
            ],
            "version": "==1.1.1"
        },
        "werkzeug": {
            "hashes": [
                "sha256:865856ebb55c4dcd0630cdd8f3331a1847a819dda7e8c750d3db6f2aa6c0209c",
                "sha256:a0b915f0815982fb2a09161cb8f31708052d0951c3ba433ccc5e1aa276507ca6"
            ],
            "version": "==0.15.4"
        }
    },
    "develop": {}
}

3. блокировка труб

Предположим, мы хотим выпустить проект в производственную среду, тогда нам нужно использоватьpipenv lockЗаказ

➜ pipenv lock

В терминале появится сообщение, подобное следующему

Locking [dev-packages] dependencies…
✔ Success!
Locking [packages] dependencies…

Эта команда создаст или обновитPipfile.lockфайл, следует отметить, что мы не должны изменять этот файл вручную.

Затем вы можете восстановить среду в производственной среде с помощью следующей команды

➜ pipenv install --ignore-pipfile

уточнить--ignore-pipfileПараметр означает, что до тех пор, пока восстановлениеPipfile.lockСписок зависимых библиотек и зависимых библиотек. Если вы хотите восстановить зависимые библиотеки в среде разработки, то есть установить[dev-packages]Можно использовать следующие зависимые библиотеки

➜ pipenv install --dev

Вышеупомянутоеpipenvпростое использование.

4. график пайпэнв

Теперь давайте рассмотрим проблемы, упомянутые ранее.

ALib -> sublib_1.0
BLib -> sublib_2.1

Aа такжеBВсе модули зависят от одной и той же библиотеки, но номера версий зависимых библиотек различаются. Используйте это времяpipenv installпохоже на следующее

Warning: Your dependencies could not be resolved. You likely have a mismatch in your sub-dependencies.
  You can use $ pipenv install --skip-lock to bypass this mechanism, then run $ pipenv graph to inspect the situation.
Could not find a version that matches sublib=1.0,sublib=2.1

можно использовать

➜ pipenv graph

Просмотрите информацию о текущей библиотеке зависимостей проекта и ее библиотеке зависимостей и отобразите ее на уровне дерева.

Flask==1.0.1
  - click [required: >=5.1, installed: 7.0]
  - itsdangerous [required: >=0.24, installed: 1.1.0]
  - Jinja2 [required: >=2.10, installed: 2.10.1]
    - MarkupSafe [required: >=0.23, installed: 1.1.1]
  - Werkzeug [required: >=0.14, installed: 0.15.4]
pytest==4.6.2
  - atomicwrites [required: >=1.0, installed: 1.3.0]
  - attrs [required: >=17.4.0, installed: 19.1.0]
  - importlib-metadata [required: >=0.12, installed: 0.17]
    - zipp [required: >=0.5, installed: 0.5.1]
  - more-itertools [required: >=4.0.0, installed: 7.0.0]
  - packaging [required: Any, installed: 19.0]
    - pyparsing [required: >=2.0.2, installed: 2.4.0]
    - six [required: Any, installed: 1.12.0]
  - pluggy [required: >=0.12,<1.0, installed: 0.12.0]
    - importlib-metadata [required: >=0.12, installed: 0.17]
      - zipp [required: >=0.5, installed: 0.5.1]
  - py [required: >=1.5.0, installed: 1.8.0]
  - six [required: >=1.10.0, installed: 1.12.0]
  - wcwidth [required: Any, installed: 0.1.7]

В этом примере мы установилиflaskа такжеpytest,pipenv graphКоманды показывают зависимости, которые требуются каждой из них. можно также добавить--reverseпараметр

➜ pipenv graph --reverse

С помощью этого параметра можно легко анализировать конфликтующие библиотеки.

atomicwrites==1.3.0
  - pytest==4.6.2 [requires: atomicwrites>=1.0]
attrs==19.1.0
  - pytest==4.6.2 [requires: attrs>=17.4.0]
click==7.0
  - Flask==1.0.1 [requires: click>=5.1]
itsdangerous==1.1.0
  - Flask==1.0.1 [requires: itsdangerous>=0.24]
MarkupSafe==1.1.1
  - Jinja2==2.10.1 [requires: MarkupSafe>=0.23]
    - Flask==1.0.1 [requires: Jinja2>=2.10]
more-itertools==7.0.0
  - pytest==4.6.2 [requires: more-itertools>=4.0.0]
pip==19.1.1
py==1.8.0
  - pytest==4.6.2 [requires: py>=1.5.0]
pyparsing==2.4.0
  - packaging==19.0 [requires: pyparsing>=2.0.2]
    - pytest==4.6.2 [requires: packaging]
setuptools==41.0.1
six==1.12.0
  - packaging==19.0 [requires: six]
    - pytest==4.6.2 [requires: packaging]
  - pytest==4.6.2 [requires: six>=1.10.0]
wcwidth==0.1.7
  - pytest==4.6.2 [requires: wcwidth]
Werkzeug==0.15.4
  - Flask==1.0.1 [requires: Werkzeug>=0.14]
wheel==0.33.4
zipp==0.5.1
  - importlib-metadata==0.17 [requires: zipp>=0.5]
    - pluggy==0.12.0 [requires: importlib-metadata>=0.12]
      - pytest==4.6.2 [requires: pluggy>=0.12,<1.0]
    - pytest==4.6.2 [requires: importlib-metadata>=0.12]

5. Другие команды

удалить зависимость

➜ pipenv uninstall numpy

удалить все зависимости

➜ pipenv uninstall --all

➜ pipenv uninstall --all-dev

--all-devуказывается для удаления всехсреда разработкизависимость.

Проверятьvenvпуть к каталогу

➜ pipenv --venv

/Users/mac/.local/share/virtualenvs/pipenvdemo-fHPp2Wq9

Просмотр текущего пути к проекту

➜ pipenv --where

/Users/mac/PycharmProjects/pipenvdemo

0x02 Суммировать

от текущего использованияpip+venvНачиная с проблем, с которыми сталкивается инструмент управления пакетами, упоминается, что проблема, возникающая таким образом, заключается в том, что зависимые библиотеки и их зависимые библиотеки могут иметь конфликты версий и проблемы с управлением. Итак, кто-то предложил новый инструмент управления пакетамиpipenv. Он имеет два основных файлаPipfileа такжеPipfile.lockфайл, первый используется для указания непосредственно зависимой информации о библиотеке в текущем проекте, а второй указываетИнформация о зависимой зависимой библиотеке через зависимуюhashзначение и номер версии, чтобы определить согласованность зависимой библиотеки.

0x03 Ссылка