Importuj moduł z podfolderu

104

Chcę zaimportować podfoldery jako moduły. Dlatego każdy podfolder zawiera plik __init__.py. Moja struktura folderów jest następująca:

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

W moim głównym skrypcie importuję

from dirFoo.foofactory import FooFactory

W tym pliku fabrycznym dołączam moduły podrzędne:

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

Jeśli zadzwonię do mojej fabryki, otrzymuję błąd, że Python nie może zaimportować podmodułów foo1 i 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
źródło

Odpowiedzi:

137

Nie ma potrzeby zadzierać ze swoim PYTHONPATHlub sys.pathtutaj.

Aby poprawnie używać importu bezwzględnego w pakiecie, należy również dołączyć nazwę pakietu „root”, np .:

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

Lub możesz użyć importu względnego :

from .dirfoo1.foo1 import Foo1
from .dirfoo2.foo2 import Foo2
Rob Wouters
źródło
47
Jedna rzecz do zapamiętania! dodaj __init__.pydo każdego podfolderu, z którego importujesz.
Aziz Alto,
6
Pusty __init__.pymoże załatwić sprawę.
cerebrou
1
Jaka byłaby składnia, gdyby poprzednio Foo1znajdowała się w katalogu nadrzędnym i była zakodowana w podobny sposób from Foo1 import *. Czy jest sposób na osiągnięcie tego samego efektu, aby nie musieć poprzedzać wszystkiego prefiksem Foo1?
jxramos,
1
@AzizAlto: bez twojego komentarza to rozwiązanie nie jest zbyt przydatne
Alex
21

Wystarczy powiadomić tutaj. (od newbee, keviv22)

Nigdy i przenigdy nie nadawaj folderów lub plików symbolom takim jak „-” lub „_” dla własnego dobra. Jeśli tak zrobiłeś, możesz napotkać kilka problemów. tak jak mój, powiedzmy, chociaż twoje polecenie importu jest poprawne, nie będziesz w stanie pomyślnie zaimportować żądanych plików, które są dostępne w takich nazwanych folderach.

Nieprawidłowe nazwy folderów w następujący sposób:

  • Folder klas ogólnych
  • Generic_Classes_Folder

prawidłowe nazwy folderów dla powyższych:

  • GenericClassesFolder lub Genericclassesfolder lub genericClassesFolder (lub w ten sposób bez żadnych spacji ani specjalnych symboli wśród słów)

Jaki błąd popełniłem:

weź pod uwagę strukturę plików.

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

Co chciałem zrobić?

  • z testFile.py, chciałem zaimportować plik „targetClass.py” do pliku Generic-Class-Folder, aby użyć funkcji o nazwie „functionExecute” w pliku „targetClass.py”

Jakie polecenie wydałem?

  • z „testFile.py”, napisano polecenie, from Core.Generic-Class-Folder.targetClass import functionExecute
  • Masz błędy, takie jak SyntaxError: invalid syntax

Próbowałem wielu wyszukiwań i przeglądałem wiele pytań związanych z przepełnieniem stosu i nie mogłem zdecydować, co poszło nie tak. Wielokrotnie sprawdzałem swoje pliki, użyłem __init__.pypliku, wstawiłem ścieżkę środowiska i bardzo się martwiłem, co poszło nie tak ......

I po długim, długim czasie odkryłem to podczas rozmowy z moim przyjacielem. Jestem trochę głupi, używając takich konwencji nazewnictwa. Nigdy nie powinienem używać spacji ani specjalnych symboli do definiowania nazwy żadnego folderu lub pliku. Więc to właśnie chciałem przekazać. Miłego dnia!

(przepraszam za ogromny post w tej sprawie ... po prostu odpuszczam moje frustracje ... :) Dzięki!)

Vivek22
źródło
23
Powodowałyby to spacje i myślniki („-”), ale podkreślenia („_”) powinny nadal działać prawidłowo.
cowlinator
6

Ustaw zmienną środowiskową PYTHONPATH. Na przykład jak ta PYTHONPATH =.: .. (dla rodziny * nix).

Możesz także ręcznie dodać swój bieżący katalog (w twoim przypadku src) do pythonpath:

import os
import sys
sys.path.insert(0, os.getcwd())
Max Kamenkov
źródło
2

Powiedz, że Twój projekt ma następującą strukturę:

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

Wewnątrz run.pymożesz zaimportować skrypty pierwszy i drugi:

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

Teraz, wciąż w środku run.py, będziesz mógł wywoływać ich metody za pomocą:

One.method_from_one(param)
Two.method_from_two(other_param)
Flavio Wuensche
źródło
1

Po prostu utwórz pusty plik ___init____.py i dodaj go w katalogu głównym, a także w całym podkatalogu / folderze aplikacji w języku Python, w którym znajdują się inne moduły Pythona.

Abhijit Pritam Dutta
źródło
-2

Wystąpiły problemy, nawet gdy init .py istniał w podfolderze, a jedyne, czego brakowało, to dodanie „as” po zaimportowaniu

from folder.file import Class as Class
import folder.file as functions
Tomas Trdla
źródło