#python #python-3.x #import
#python #python-3.x #импорт
Вопрос:
Это моя ситуация. У меня есть следующая структура каталогов:
$ls -R .:
driver.py package
./package:
dependent.py __init__.py standalone.py
driver.py:
#!/usr/bin/env python
from package.dependent import add_n
if __name__=='__main__':
print(add_n(2,2))
dependent.py:
#!/usr/bin/env python
from standalone import add_1
def add_n(x, n):
for _ in range(n):
x = add_1(x)
return x
standalone.py:
#!/usr/bin/env python
def add_1(x):
return x 1
Теперь, в зависимости от моего варианта использования, я хочу запустить dependent.py
напрямую или импортировать его в driver.py
. Это проблема, с которой я сталкиваюсь:
- Запуск
dependent.py
работает, только если при импорте нет точкиadd_1
. Если он есть, он выдает следующую ошибку:
Traceback (most recent call last):
File "dependent.py", line 3, in <module>
from .standalone import add_1
ModuleNotFoundError: No module named '__main__.standalone'; '__main__' is not a package
- Запуск
package.py
работает, только если при импорте есть точкаadd_1
. Если такового нет, выдается следующая ошибка:
Traceback (most recent call last):
File "driver.py", line 3, in <module>
from package.dependent import add_n
File "/home/su0/scratch/package/dependent.py", line 3, in <module>
from standalone import add_1
ModuleNotFoundError: No module named 'standalone'
Я хочу, чтобы работали оба сценария. Это потому, что в реальном проекте внутри пакета есть зависимости, которые импортируют другие модули. И я хочу иметь возможность импортировать его также как пакет. Приветствуется любая помощь.
Спасибо.
Комментарии:
1. Что
pwd
в этом случае?2. Извините, я не понимаю. Это просто некоторый каталог (каталог в моем доме).
Ответ №1:
Лучше всего было бы действительно упаковать код, а затем использовать абсолютный импорт в dependent.py
. Однако в качестве обходного пути вы можете использовать один из следующих вариантов:
Расширяем путь в driver.py
Перед import package.dependent
вы можете добавить следующие строки:
import sys
sys.path.append('package')
Затем используйте оператор import без точек в dependent.py
. Это работает, поскольку теперь package
находится на пути к поиску модулей, включая standalone.py
.
Используйте условный импорт в dependent.py
Вы можете изменить импорт в dependent.py
следующим образом:
if __name__ == '__main__':
from standalone import ...
else:
from .standalone import ...
Комментарии:
1. Выполняется ли условный импорт в самом верху, чтобы заменить исходную инструкцию import?
2. Да, он должен заменить исходный. Он может использоваться где угодно, но, очевидно, должен быть выполнен до того, как вы попытаетесь использовать импортированную функцию. В любом случае я бы предпочел использовать вариант 1 (упаковать код) или вариант 2 (расширить
sys.path
); вариант 3 (условный импорт) подразумевает, чтоdependent.py
«знает», что он будет импортирован куда-то еще, но тогда вы все равно могли бы просто поместить код в отдельный модуль.