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

Развернуть путь поиска Python к другому источнику

Я только что присоединился к проекту с довольно большой существующей базой кода. Мы разрабатываем в Linux и не используем и IDE. Мы запускаем командную строку. Я пытаюсь понять, как заставить python искать правильный путь при запуске модулей проекта. Например, когда я запускаю что-то вроде:

python someprojectfile.py

Я получаю

ImportError: no module named core.'somemodule'

Я получаю это для всего моего импорта, я предполагаю, что это проблема с этим путем.

TL;DR:

Как получить Python для поиска ~/codez/project/ и всех файлов и папок для файлов *.py во время операций импорта.

4b9b3361

Ответ 1

Есть несколько возможных способов сделать это:

  • Задайте для переменной среды PYTHONPATH список каталогов, разделенных двоеточиями, для поиска импортированных модулей.
  • В вашей программе используйте sys.path.append('/path/to/search'), чтобы добавить имена каталогов, которые Python будет искать для поиска импортированных модулей. sys.path - это просто список каталогов, которые Python ищет каждый раз, когда ему предлагается импортировать модуль, и вы можете изменять его по мере необходимости (хотя я бы не рекомендовал удалять какие-либо из стандартных каталогов!). Все каталоги, которые вы поместите в переменную окружения PYTHONPATH, будут вставлены в sys.path при запуске Python.
  • Используйте site.addsitedir, чтобы добавить каталог в sys.path. Разница между этим и простым добавлением заключается в том, что при использовании addsitedir он также ищет файлы .pth в этом каталоге и использует их для возможного добавления дополнительных каталогов в sys.path в зависимости от содержимого файлов. Смотрите документацию для более подробной информации.

Какой из них вы хотите использовать, зависит от вашей ситуации. Помните, что когда вы распространяете ваш проект среди других пользователей, они обычно устанавливают его таким образом, что файлы кода Python будут автоматически обнаруживаться импортером Python (то есть пакеты обычно устанавливаются в каталог site-packages), так что если вы возитесь с sys.path в вашем коде, это может быть ненужным и даже может иметь неблагоприятные последствия, когда этот код выполняется на другом компьютере. Что касается разработки, я бы рискнул предположить, что настройка PYTHONPATH обычно является наилучшим способом.

Тем не менее, когда вы используете что-то, что просто запускается на вашем собственном компьютере (или когда у вас нестандартные настройки, например, иногда в каркасах веб-приложений), вполне обычно делать что-то вроде

import sys
from os.path import dirname
sys.path.append(dirname(__file__))

Ответ 2

Вы также должны прочитать о пакетах python здесь: http://docs.python.org/tutorial/modules.html.

Из вашего примера я бы предположил, что у вас действительно есть пакет в ~/codez/project. Файл __init__.py в каталоге python отображает каталог в пространство имен. Если у ваших подкаталогов есть файл __init__.py, вам нужно только добавить базовый каталог к вашему PYTHONPATH. Например:

PYTHONPATH = $ PYTHONPATH: $ HOME/adaifotis/проект

В дополнение к тестированию переменной среды PYTHONPATH, как объясняет Дэвид, вы можете протестировать ее в python следующим образом:

$ python
>>> import project                      # should work if PYTHONPATH set
>>> import sys
>>> for line in sys.path: print line    # print current python path

...

Ответ 3

Я знаю, что эта ветка немного устарела, но мне потребовалось некоторое время, чтобы понять ее суть, поэтому я хотел поделиться ею.

В моем проекте у меня был основной скрипт в родительском каталоге, и, чтобы дифференцировать модули, я помещал все поддерживающие модули в подпапку под названием "модули". В моем основном скрипте я импортирую эти модули следующим образом (для модуля, называемого report.py):

from modules.report import report, reportError

Если я назову свой основной скрипт, это сработает. ОДНАКО, я хотел протестировать каждый модуль, включив в них main(), и каждый из них вызывал каждый, как:

python modules/report.py

Теперь Python жалуется, что не может найти "модуль, называемый модулями". Ключевым моментом здесь является то, что по умолчанию Python включает в себя папку скрипта в своем пути поиска, но не CWD. Так что эта ошибка говорит, на самом деле: "Я не могу найти подпапку модулей". Это связано с тем, что подкаталог "modules" не существует из каталога, в котором находится модуль report.py.

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

import sys

sys.path.append(".")

Теперь Python ищет CWD (текущий каталог), находит подпапку "modules", и все хорошо.

Ответ 4

Я прочитал этот вопрос, ища ответ, и ему не понравилось.

Итак, я написал быстрое и грязное решение. Просто поместите это где-нибудь на свой sys.path, и он добавит любой каталог под folder (из текущего рабочего каталога) или под abspath:

#using.py

import sys, os.path

def all_from(folder='', abspath=None):
    """add all dirs under `folder` to sys.path if any .py files are found.
    Use an abspath if you'd rather do it that way.

    Uses the current working directory as the location of using.py. 
    Keep in mind that os.walk goes *all the way* down the directory tree.
    With that, try not to use this on something too close to '/'

    """
    add = set(sys.path)
    if abspath is None:
        cwd = os.path.abspath(os.path.curdir)
        abspath = os.path.join(cwd, folder)
    for root, dirs, files in os.walk(abspath):
        for f in files:
            if f[-3:] in '.py':
                add.add(root)
                break
    for i in add: sys.path.append(i)

>>> import using, sys, pprint
>>> using.all_from('py') #if in ~, /home/user/py/
>>> pprint.pprint(sys.path)
[
#that was easy
]

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

Ответ 5

Самый простой способ - создать файл "any_name.pth" и поместить его в папку "\ Lib\site-packages". Вы должны найти эту папку везде, где установлен python.

В этом файле поместите список каталогов, в которые вы хотите сохранить модули для импорта. Например, создайте строку в этом файле следующим образом:

C:\Users\пример...\пример

Вы сможете сказать, что это работает, запустив это в python:

import sys
for line in sys: print line

Вы увидите, что ваш каталог распечатан, среди прочих, откуда вы также можете импортировать. Теперь вы можете импортировать файл "mymodule.py", который находится в этом каталоге так же легко, как:

import mymodule

Это не будет импортировать подпапки. Для этого вы можете представить себе создание python script для создания файла .pth, содержащего все подпапки папки, которую вы определяете. Возможно, он запускается при запуске.

Ответ 7

Новая опция для старого вопроса.
Установка пакета fail2ban в Debian, похоже, жестко запрограммирована для установки в /usr/lib/python3/dist-packages/fail2ban путь не в python3 sys.path.


> python3
Python 3.7.3 (v3.7.3:ef4ec6ed12, Jun 25 2019, 18:51:50)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', '/usr/lib/python37.zip', '/usr/lib/python3.7', '/usr/lib/python3.7/lib-dynload', '/usr/lib/python3.7/site-packages']
>>>

поэтому вместо простого копирования я (bash) связал библиотеку с более новыми версиями.
Будущие обновления исходного приложения также будут автоматически применяться к связанным версиям.

 if [ -d /usr/lib/python3/dist-packages/fail2ban ]
   then
      for d in /usr/lib/python3.*
      do
         [ -d ${d}/fail2ban ] || \
            ln -vs /usr/lib/python3/dist-packages/fail2ban ${d}/
      done
   fi