Импортировать модуль из подпапки

104

Я хочу импортировать подпапки как модули. Следовательно, каждая подпапка содержит файл __init__.py. Моя структура папок такая:

src\
  main.py
  dirFoo\
    __init__.py
    foofactory.py
    dirFoo1\
      __init__.py
      foo1.py
    dirFoo2\
      __init__.py
      foo2.py

В моем основном скрипте я импортирую

from dirFoo.foofactory import FooFactory

В этот заводской файл я включаю подмодули:

from dirFoo1.foo1 import Foo1
from dirFoo2.foo2 import Foo2

Если я вызываю свой foofactory, я получаю сообщение об ошибке, этот python не может импортировать подмодули foo1 и foo2:

Traceback (most recent call last):
  File "/Users/tmp/src/main.py", line 1, in <module>
from dirFoo.foofactory import FooFactory
  File "/Users/tmp/src/dirFoo/foofactory.py", line 1, in    <module>
from dirFoo1.foo1 import Foo1
    ImportError: No module named dirFoo1.foo1
Razer
источник

Ответы:

137

Не нужно связываться с вашим PYTHONPATHили sys.pathздесь.

Чтобы правильно использовать абсолютный импорт в пакете, вы должны также включить "корневой" пакет, например:

from dirFoo.dirFoo1.foo1 import Foo1
from dirFoo.dirFoo2.foo2 import Foo2

Или вы можете использовать относительный импорт :

from .dirfoo1.foo1 import Foo1
from .dirfoo2.foo2 import Foo2
Роб Воутерс
источник
47
Одно нужно помнить! добавить __init__.pyво все подпапки, из которых выполняется импорт.
Азиз Альто
6
Пустой __init__.pyможет сделать работу.
cerebrou
1
Каким был бы синтаксис, если бы ранее Foo1был в родительском каталоге, а один кодировал что-то вроде from Foo1 import *. Есть ли способ добиться того же эффекта, чтобы вам не приходилось все ставить префиксом Foo1?
jxramos
1
@AzizAlto: без вашего комментария это решение не очень полезно
Alex
21

Просто уведомить здесь. (от новичка, keviv22)

Никогда и когда-либо ради вашего же блага называть папки или файлы такими символами, как «-» или «_». Если вы это сделаете, у вас может возникнуть несколько проблем. как и моя, скажем, хотя ваша команда для импорта верна, вы не сможете успешно импортировать желаемые файлы, которые доступны внутри таких именованных папок.

Недопустимые имена папок:

  • Папка Generic-Classes
  • Generic_Classes_Folder

допустимые имена папок для выше:

  • GenericClassesFolder или Genericclassesfolder или genericClassesFolder (или как это без пробелов или специальных символов между словами)

Какую ошибку я сделал:

рассмотрите файловую структуру.

Parent
   . __init__.py
   . Setup
     .. __init__.py
     .. Generic-Class-Folder
        ... __init__.py
        ... targetClass.py
   . Check
     .. __init__.py
     .. testFile.py

Что я хотел сделать?

  • из testFile.py я хотел импортировать файл targetClass.py внутри файла Generic-Class-Folder, чтобы использовать функцию с именем «functionExecute» в файле targetClass.py

Какую команду я сделал?

  • из testFile.py, написал команду, from Core.Generic-Class-Folder.targetClass import functionExecute
  • Есть ошибки вроде SyntaxError: invalid syntax

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

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

(извините за огромный пост по этому поводу ... просто отпустите мои разочарования .... :) Спасибо!)

Вивек22
источник
23
Пробелы и дефисы («-») могут вызвать это, но символы подчеркивания («_») должны работать нормально.
cowlinator
6

Задайте переменную среды PYTHONPATH. Например, PYTHONPATH =.: .. (для семейства * nix).

Также вы можете вручную добавить свой текущий каталог (в вашем случае src) в pythonpath:

import os
import sys
sys.path.insert(0, os.getcwd())
Макс Каменков
источник
2

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

+---MyPythonProject
|   +---.gitignore
|   +---run.py
|   |   +---subscripts
|   |   |   +---script_one.py
|   |   |   +---script_two.py

Внутри run.pyвы можете импортировать первый и второй скрипты:

from subscripts import script_one as One
from subscripts import script_two as Two

Теперь, все еще внутри run.py, вы сможете вызывать их методы с помощью:

One.method_from_one(param)
Two.method_from_two(other_param)
Флавио Вуэнше
источник
1

Просто создайте пустой файл ___init____.py и добавьте его в корень, а также во все подкаталог / папку вашего приложения python, где у вас есть другие модули python.

Абхиджит Притам Дутта
источник
-2

Были проблемы, даже когда init .py существовал в подпапке, и все, что не хватало, это добавление `` как '' после импорта

from folder.file import Class as Class
import folder.file as functions
Томаш Трдла
источник