Зачем использовать sys.path.append (путь) вместо sys.path.insert (1, путь)?

88

Изменить: основываясь на комментарии Ульфа Ромпе, важно использовать «1» вместо «0» , иначе вы нарушите sys.path .

Я занимаюсь питоном уже довольно давно (более года), и меня всегда смущает, почему люди рекомендуют вам использовать sys.path.append()вместо sys.path.insert(). Позвольте мне продемонстрировать.

Скажем, я работаю над модулем PyWorkbooks (установленным на моем компьютере), но одновременно работаю над другим модулем (скажем, PyJob), который включает PyWorkbooks. Когда я работаю над PyJob, я нахожу ошибки в PyWorkbooks, которые исправляю, поэтому я хотел бы импортировать версию для разработки.

Есть несколько способов работать с обоими (например, я мог бы поместить свой проект PyWorkbooks в PyJob), но иногда мне все равно нужно поиграть с путем. Однако я не могу просто сделать a sys.path.append()с папкой, в которой находится PyWorkbooks . Зачем? Потому что python сначала найдет мои установленные PyWorkbooks!

Вот почему вам нужно сделать sys.path.insert (1, path_to_dev_pyworkbooks)

В итоге:

sys.path.append(path_to_dev_pyworkbooks)
import PyWorkbooks # does NOT import dev pyworkbooks, imports installed one

или:

sys.path.insert(1, path_to_dev_pyworkbooks) # based on comments you should use **1 not 0**
import PyWorkbooks # imports correct file

Это вызывало у меня несколько зависаний в прошлом, и мне бы очень хотелось, чтобы мы (как сообщество) начали рекомендовать sys.path.insert(1, path), как будто вы вручную вставляете путь, я думаю, можно с уверенностью сказать, что это тот путь, который вы хотите использовать!

Или у меня что-то не так? Этот вопрос иногда беспокоит меня, и я хотел, чтобы он был открыт!

Гарретт Берг
источник
3
Я сделал, sys.path.insert(1, dev_folder)но он все еще не находит модуль dev, а использует только установленный модуль. Как это исправить?
endolith

Ответы:

47

Если у вас есть несколько версий пакета / модуля, вам нужно использовать virtualenv (выделено мной):

virtualenv это инструмент для создания изолированных сред Python.

Основная проблема, которую решают, - это зависимости и версии, а также косвенные разрешения. Представьте, что у вас есть приложение, которому требуется версия 1 LibFoo, а другому приложению требуется версия 2. Как вы можете использовать оба этих приложения? Если вы установите все в/usr/lib/python2.7/site-packages (или в другое стандартное расположение вашей платформы), легко попасть в ситуацию, когда вы непреднамеренно обновляете приложение, которое не следует обновлять.

Или, в более общем плане, что, если вы хотите установить приложение и оставить его в покое ? Если приложение работает, любое изменение в его библиотеках или версиях этих библиотек может нарушить работу приложения.

Кроме того, что, если вы не можете установить пакеты в глобальный site-packagesкаталог? Например, на общем хосте.

Во всех этих случаях virtualenvмогу вам помочь. Он создает среду, в которой есть собственные каталоги установки, которые не разделяют библиотеки с другими средами virtualenv (и, при необходимости, не имеют доступа к глобально установленным библиотекам).

Вот почему люди считают, insert(0, что ошибаются - это неполное временное решение проблемы управления несколькими средами.

agf
источник
Спасибо, я смутно знал, что что-то подобное существует, но до сих пор не проверял это. Итак, что я должен был бы сделать с этим, так это запустить все из интерпретатора в виртуальной среде ... это тоже может сработать. Благодарность!
Гарретт Берг
1
Это предложение, но не дает прямого ответа на вопрос (например, у меня есть веские причины не использовать, virtualenvи я действительно ищу связанный ответ на OP)
Стивен Бош
@javadba Это может быть правдой для вашего случая, но большинству людей, задающих этот вопрос, следует использовать venv.
agf 06
46

Если вам действительно нужно использовать sys.path.insert, оставьте sys.path [0] как есть:

sys.path.insert(1, path_to_dev_pyworkbooks)

Это может быть важно, поскольку сторонний код может полагаться на соответствие документации sys.path :

Как инициализируется при запуске программы, первый элемент этого списка, путь [0], - это каталог, содержащий сценарий, который использовался для вызова интерпретатора Python.

Ульф Ромпе
источник
13

вы путаете понятия добавления и добавления. следующий код добавляется к началу:

sys.path.insert(1,'/thePathToYourFolder/')

он помещает новую информацию в начало (ну, во-вторых, если быть точным) последовательности поиска, которую будет проходить ваш интерпретатор. sys.path.append()помещает вещи в самый конец поисковой последовательности.

желательно, чтобы вы использовали что-то вроде virtualenvвместо того, чтобы вручную кодировать каталоги пакетов в PYTHONPATHкаждый раз. для настройки различных экосистем, разделяющих пакеты вашего сайта и возможные версии python, прочтите эти два блога:

  1. введение в экосистемы Python

  2. начальная загрузка виртуальных сред Python

Если вы все же решите пойти по пути изоляции среды, вам, безусловно, будет полезно заглянуть в virtualenvwrapper: http://www.doughellmann.com/docs/virtualenvwrapper/

самхан13
источник
1
Ссылки «Введение в экосистемы Python», «Начальная загрузка виртуальных сред Python» больше не используются, пожалуйста, подумайте об их обновлении.
Прадип Сингх,