Импортировать библиотеку, которая находится в одной папке с текущей папкой - PullRequest
0 голосов
/ 11 февраля 2019

Со структурой папок

lib/
    abcd/
        __init.py__
        lib.py
app.py

работает код

from lib.abcd import lib

.Но с такой файловой структурой:

bin/
    app.py
lib/
    abcd/
        __init.py__
        lib.py

код

from ..lib.abcd import lib     

выдает ошибку импорта.

Как правильно выполнить import, когдабиблиотека находится в одной папке текущей папки? (или подпапка одной папки)

Я знаю, что может быть какой-то хак, который включает добавление lib/ в PATH, но есть ли элегантный Pythonicрешение?

Если нет, существует ли реальная внутренняя причина, по которой пользователи не могут выполнять этот простой импорт простым способом?

Ответы [ 2 ]

0 голосов
/ 05 апреля 2019

Способы сделать это


Метод # 1: Использование модуля sys: Вы можете легко выполнить то, что пытаетесь сделать, используя модуль sys.Чтобы импортировать пакет lib, вы можете использовать один из двух кодов, перечисленных ниже:

import sys
sys.path.append('<PATH_TO_LIB_FOLDER>')

from lib.abcd import lib

или

import sys
sys.path.insert(0, '<PATH_TO_LIB_FOLDER>')

Метод № 2: ИспользованиеМодуль os: Другой способ - использовать модуль os.Вот пример кода, который импортирует модуль lib с использованием модуля os, вызывая метод os.path.join:

import os

path = os.path.join("<PATH>/lib/abcd", "lib")
from lib.abcd import lib

Метод № 3: Добавьте модуль в свойPYTHONPATH: В большинстве случаев это не лучший метод, но если вы не хотите продолжать использовать модуль sys или os для импорта lib, это идеальный вариант.Все, что вам нужно сделать, это набрать это в своем терминале bash:

export PYTHONPATH=<PATH_TO_LIB> python lib.py

Затем в вашей оболочке python вы можете импортировать его следующим образом:

from lib.abcd import lib

Метод# 4: Объедините модуль sys и os (рекомендуется): Это самый эффективный метод, который сэкономит вам много времени.Этот код объединяет модули os и sys следующим образом:

import sys, os
sys.path.append(os.path.abspath(os.path.join('..', 'lib')))

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

from lib.abcd import lib

Как всекоды работают:

Все приведенные выше коды очень просты.Во всех примерах, кроме «Метод № 3» , временно добавьте ваш модуль в PYTHONPATH. "Метод # 3" , с другой стороны, добавляет модуль к вашему PYTHONPATH навсегда.

0 голосов
/ 04 апреля 2019

Внешний вид уровня поверхности

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

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

Вы можете добавить к пути Python во время выполнения:

    import sys
    sys.path.insert(0, '../lib')

    import file  

Вы также можете использовать sys.path.append('../lib'), но тогда он будет найден последним в вашем пути и может быть переопределен предыдущимпути записи.

Я внимательно прочитал документацию по импорту , и, насколько я могу судить, ответ на ваш вопрос - нет, это невозможно сделать в чисто «Pythonic».путь.

Более подробно:

Более глубокое изучение документации по импорту объясняет это:

Оператор импорта объединяет две операции;он ищет названный модуль, а затем связывает результаты этого поиска с именем в локальной области видимости.Операция поиска оператора import определяется как вызов функции __ import __ () с соответствующими аргументами.Возвращаемое значение __ import __ () используется для выполнения операции привязки имени в операторе импорта.

Более пристальное внимание на __ import __ :

__ import __ (name, globals = None, localals = None, fromlist = (), level = 0)

Примечание : Это расширенная функция, которая не требуется в повседневном программировании на Python, в отличие от importlib.import_module () .

Эта функция вызывается оператором импорта.Его можно заменить (импортировав встроенный модуль и назначив встроенным .__ import__), чтобы изменить семантику оператора импорта, но делать это настоятельно не рекомендуется, так как обычно проще использовать ловушки импорта (см. PEP 302) для достиженияте же цели и не вызывают проблем с кодом, который предполагает, что используется реализация импорта по умолчанию.Прямое использование __import __ () также не рекомендуется в пользу уровня importlib.import_module () .

, указывающего, использовать ли абсолютный или относительный импорт.0 (по умолчанию) означает выполнение только абсолютного импорта.Положительные значения для уровня указывают количество родительских каталогов для поиска относительно каталога модуля, вызывающего __import __ () (подробности см. В PEP 328).

Это заставляет меня думать, что вы можете указатьlevel каким-то образом, который может заставить импорт автоматически смотреть на родительский путь.Я предполагаю, что когда import вызывается из вашего app.py, который не находится в его собственном каталоге, level устанавливается на 0, и он ищет тот же уровень и глубже.

Когда вы вызываете import в app.py из подпапки, level по-прежнему имеет значение 0 и, следовательно, не может найти другие каталоги над ним.Я исследую «Pythonic» способ установки этого уровня на 1 при запуске вашего скрипта, который может решить эту проблему.

...