Подтвердить что ты не робот

Эффект использования sys.path.insert(0, путь) и sys.path(добавление) при загрузке модулей

Недавно у меня возникла проблема с python ImportError, где модуль был найден при запуске на моем локальном компьютере, но не найден на сервере CI. Я решил эту проблему, заменив sys.path.append(path) на мой script на sys.path.insert(0, path), где path - это расположение строкового модуля.

Поскольку это мой модуль, а не установленный пакет (связанный вопрос), почему порядок путей устраняет эту проблему?

4b9b3361

Ответ 1

Поскольку python проверяет каталоги в последовательном порядке, начиная с первого каталога в списке sys.path, пока не найдет файл .py, который он искал.

В идеале текущий каталог или каталог script является первым, всегда первым элементом в списке, если вы не измените его, как вы это делали. Из документация -

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

Итак, скорее всего, у вас был файл .py с тем же именем, что и модуль, из которого вы пытались импортировать, в текущем каталоге (где выполнялся script).

Кроме того, примечание о ImportError, можно сказать, что ошибка импорта говорит - ImportError: No module named main - это не значит, что main.py перезаписано, нет, если это было перезаписано, у нас не возникнут проблемы с его чтением. Его некоторый модуль выше этого, который был перезаписан с помощью. py или другого файла.

Пример -

Моя структура каталогов выглядит как

 - test
    - shared
         - __init__.py
         - phtest.py
  - testmain.py

Теперь из testmain.py я вызываю from shared import phtest, он отлично работает.

Теперь скажем, что я представляю shared.py в каталоге test, например -

 - test
    - shared
         - __init__.py
         - phtest.py
  - testmain.py 
  - shared.py

Теперь, когда я пытаюсь выполнить from shared import phtest из testmain.py, я получу ошибку -

ImportError: cannot import name 'phtest'

Как вы можете видеть выше, файл, вызывающий проблему, составляет shared.py, а не phtest.py.

Ответ 2

Я новичок в Python, и я нашел ответ Ананда очень хорошим, но довольно сложным для меня, поэтому я пытаюсь переформулировать:

1) insert и append не являются специфическими для sys.path, и, как и на других языках, они добавляют элемент в список или массив и:
* append(item) добавить item в конец списка,
* insert(n, item) вставляет item в n-ю позицию в списке (0 в начале, 1 после первого элемента и т.д.).

2) Как сказал Ананд, python ищет файлы импорта в каждом каталоге пути в порядке пути, так:
* Если у вас нет конфликтов имен файлов, порядок пути не влияет,
* Если вы посмотрите на функцию, уже определенную в пути, и вы используете append, чтобы добавить свой путь, вы не получите свою функцию, а предопределенную.

Но я думаю, что лучше использовать append, а не insert, чтобы не перегружать стандартное поведение Python и использовать недвусмысленные имена для ваших файлов и методов.