Імпорт модуля з підпапки


104

Я хочу імпортувати підпапки як модулі. Тому кожна підпапка містить a __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

Відповіді:


136

Не потрібно возитися з вашим PYTHONPATHчи sys.pathтут.

Для правильного використання абсолютного імпорту в пакет слід також включити "root" ім'я пакета, наприклад:

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: без вашого коментаря це рішення не дуже корисне
Олексій

21

Просто щоб повідомити тут. (від новачка, кевів22)

Ніколи і ніколи задля власного блага не називайте папки або файли символами типу "-" або "_". Якщо ви зробили це, ви можете зіткнутися з кількома проблемами. як, наприклад, моя, скажімо, хоча ваша команда для імпорту є правильною, ви не зможете успішно імпортувати потрібні файли, наявні у таких названих папках.

Недійсні імена папок:

  • Загальні класи-папки
  • Generic_Classes_Folder

дійсні назви папок для вище:

  • GenericClassesFolder або Genericclasses Folder або 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

Спробував багато пошукових запитів і переглянув багато запитань щодо стаціонарного потоку і не зміг вирішити, що пішло не так. Я перетинав свої файли кілька разів, я використав __init__.pyфайл, вставив шлях оточення і дуже переживаю, що пішло не так ......

І через багато-тривалий час я зрозумів це, розмовляючи зі своїм другом. Мені мало дурно використовувати такі умови іменування. Я ніколи не повинен використовувати пробіл чи спеціальні символи для визначення імені для будь-якої папки чи файлу. Отже, це те, що я хотів передати. Гарного дня!

(вибачте за величезний пост з цього приводу ... просто відпустіть мої розчарування .... :) Дякую!)


22
Пробіли та тире ("-") спричинили б це, але підкреслення ("_") все одно повинні працювати добре.
ковбасник

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.