Python 'ImportError: Нет модуля с именем' при импорте модулей из пакетов

Я столкнулся с ошибкой Python «ImportError: No module named ...» при попытке импортировать модуль Python, который находится в другом пакете Python, из модуля, который находится в другом пакете Python. На следующем изображении показана структура каталогов:

Структура каталогов проекта с помощью PyCharm

Следует отметить, что я получаю эту ошибку только тогда, когда запускаю сценарий с моего терминала, тогда как при выполнении через PyCharm этот сценарий успешно запускается. Ошибка при запуске из терминала выглядит следующим образом:

Traceback (most recent call last):
File "social_networks/linked_data.py", line 15, in <module>
    from text_analysis.text_refinement import camel_case_split
ImportError: No module named 'text_analysis'

Я безуспешно пробовал разные способы импорта, например следующие:

Способ-1:

sys.path.insert(0, os.path.realpath('../text_analysis'))
from text_analysis.text_refinement import camel_case_split

Способ-2:

from text_analysis.text_refinement import camel_case_split

Как решить эту проблему?


person Chiranga Alwis    schedule 28.02.2017    source источник
comment
проверьте это, вероятно, поможет u: stackoverflow.com/ вопросы / 338768 /   -  person Vivek    schedule 28.02.2017


Ответы (1)


Укороченная версия

Измените его на:

sys.path.insert(0, os.path.realpath('./'))
from text_analysis.text_refinement import camel_case_split

Or:

sys.path.insert(0, os.path.realpath('./text_analysis'))
from text_refinement import camel_case_split

Длинная версия

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

Прежде всего, я вижу, что вы работаете над своим проектом в PyCharm. Он автоматически добавляет корень проекта в PYTHONPATH. Вы можете подробно прочитать об этом в этом поток. Поскольку PyCharm позаботится о маршрутах за вас, вам действительно не нужно

sys.path.insert(0, os.path.realpath('../text_analysis'))

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

for path in sys.path:
    print(path)

Хотя это интересная информация, она не отвечает на ваш вопрос, как запустить ее с терминала. Чтобы понять, почему он не запускается из сценария, давайте посмотрим, какие пути Python будут у вас при выполнении (слегка измененных) команд в методе-1:

sys.path.insert(0, os.path.realpath('../text_analysis'))

try:
    from text_analysis.text_refinement import camel_case_split
    camel_case_split()
except:
    for path in sys.path:
        print(path)

# output:
# ~/text_analysis (where ../text_analysis path points to)
# ~/social-network-interest-engine/social_networks (where your file is)
# ... (several other irrelevant paths) ...

Мы видим, что '../text_analysis' указывает на один каталог выше того, что вам нужно. Что произойдет, если мы удалим одну из точек и вместо этого напишем './text_analysis'? Выход вроде как нам нужен:

# output:
# ~/social-network-interest-engine/text_analysis
# ~/social-network-interest-engine/social_networks

Но мы до сих пор не импортировали функцию. Мы знаем это, потому что достигаем except части, которая печатает пути. Глядя на импорт, мы видим, что у нас есть text_analysis.text_refinement. Нам действительно нужно указывать имя каталога, если мы уже добавили его в путь? Нет, мы не. Если мы напишем

from text_refinement import camel_case_split

вместо этого мы обнаруживаем, что функция наконец-то импортирована. Следуя этой логике и предполагая, что мы хотим оставить text_analysis.text_refinement в операторе импорта (по какой-либо причине), мы также можем добавить путь по-другому:

sys.path.insert(0, os.path.realpath('./'))

Обратите внимание, однако, что этот способ вставки пути несколько хрупкий. Начальное местоположение - это путь, из которого вы вызываете python python_file.py. Если вы перешли в другой каталог, вам нужно будет соответствующим образом настроить os.path.realpath. Что вы можете сделать вместо этого:

sys.path.insert(0, 'full/path/to/application/app/folder')

Хотя это предполагает, что каталог / структура вашего проекта не изменится.

Для более подробного обзора путей и импорта вы можете узнать больше об импорте материалов из разных папок здесь, и если вы предпочитаете импорт относительного пути, это полезная ветка. Конечно, официальная документация также хорошее место для начала.

person cegas    schedule 28.02.2017
comment
Отличный ответ ... спасибо. В настоящее время я разрешаю пользователю установить путь к каталогу приложения в качестве переменной среды. - person Chiranga Alwis; 28.02.2017