Jak zaimportować klasę w tym samym katalogu lub podkatalogu?

675

Mam katalog, w którym przechowywane są wszystkie pliki .py .

bin/
   main.py
   user.py # where class User resides
   dir.py # where class Dir resides

Chcę użyć klas z user.py i dir.py w main.py .
Jak mogę zaimportować te klasy Python do main.py ?
Ponadto, jak mogę zaimportować klasę, Userjeśli user.py znajduje się w podkatalogu?

bin/
    dir.py
    main.py
    usr/
        user.py
Bin Chen
źródło

Odpowiedzi:

938

Python 2

Utwórz pusty plik wywoływany __init__.pyw tym samym katalogu co pliki. Będzie to oznaczać dla Pythona, że ​​„można importować z tego katalogu”.

Więc po prostu zrób ...

from user import User
from dir import Dir

To samo dotyczy praw, jeśli pliki znajdują się w podkatalogu - umieść również __init__.pyw podkatalogu, a następnie użyj zwykłych instrukcji importu, z notacją kropkową. Dla każdego poziomu katalogu należy dodać do ścieżki importu.

bin/
    main.py
    classes/
        user.py
        dir.py

Więc jeśli katalog zostałby nazwany „klasami”, zrobiłbyś to:

from classes.user import User
from classes.dir import Dir

Python 3

Taki sam jak poprzedni, ale poprzedź nazwę modułu przedrostkiem, .jeśli nie używa podkatalogu:

from .user import User
from .dir import Dir
Bursztyn
źródło
14
Jeśli nie__init__.py jest pusty, to cokolwiek jest, będzie dostępne po zaimportowaniu pakietu (a rzeczy, do których nie zaimportowano , nie będą w ogóle dostępne). __init__.py__init__.py
Amber
23
Dlaczego __init__.pyw ogóle potrzebny jest plik? Jeśli włożę wszystkie trzy pliki do tego samego katalogu i uruchomię main.py, będzie to możliwe importz dwóch pozostałych modułów bez niego. czego mi brakuje?
martineau,
30
Ponieważ w ten sposób Python identyfikuje katalogi, z których możesz importować. Katalog uruchomionego skryptu jest wyjątkiem - zawsze możesz z niego importować.
Amber
20
@nbro & Amber: FWIW, myślę, że coś subtelnego zmieniło się w odniesieniu do __init__.pymożliwości importowania innych modułów w tym samym katalogu. W szczególności imports innych modułów w tym samym katalogu, co __init__.pysam plik, który działał w Pythonie 2.7.8, zawiódł w Pythonie 3.4.1. Aby to naprawić, musiałem poprzedzić każdą z nich nazwą podkatalogu i kropką (tj. import moduleMusiałem zmienić na import subdirectory.module). Na szczęście po wykonaniu tej czynności nadal działało w Pythonie 2.7.8.
martineau
4
Mogę potwierdzić, że to rozwiązanie nie działa. Możesz go poprawić, zmienić lub całkowicie usunąć.
Luís de Sousa
137

Właśnie dowiedziałem się (dzięki komentarzowi Martineau ), że aby zaimportować klasy z plików w tym samym katalogu, piszesz teraz w Pythonie 3:

from .user import User
from .dir import Dir
ecp
źródło
8
jeśli spróbuję tego nie, ValueError: Attempted relative import in non-packagefrom user import User
pojawi
Używam z .fileloader importu Fileloader i otrzymuję ImportError: nie mogę zaimportować nazwy „Fileloader”
Frikster
3
@Korpel: Po dyskusjach na stackoverflow.com/questions/11536764 /... zdaję sobie sprawę, że niezależnie od tego, czy powyższy import działa, czy nie, zależy od: [1] jak wywoływany jest twój skrypt (jako pakiet czy nie) [2] gdzie rzeczywista ścieżka praca jest, kiedy go wykonać [3], jak zmienna ścieżka środowisku roboczym jest pusta
ECP
@Korpel: Zauważyłem, że. przed nazwa modułu jest wymagana tylko wtedy, gdy obecny jest plik init .py, jeśli nie. można / należy pominąć.
MUG4N
39

W twoim main.py:

from user import Class

gdzie Class jest nazwa klasy, którą chcesz zaimportować.

Jeśli chcesz wywołać metodę Class, możesz wywołać ją za pomocą:

Class.method

Pamiętaj, że __init__.pyw tym samym katalogu powinien znajdować się pusty plik.

użytkownik225312
źródło
1
Co robisz, jeśli moduł, który próbujesz zaimportować, nie ma klas? Tylko surowe funkcje? W Pythonie 2 wszystko, co musiałem zrobić, to „moduł importu”. Nie działa w Pythonie 3,
podobnie
2
Działa to w python3 po usunięciu pliku __init__.py.
Engineforce
13

Możesz zaimportować moduł i uzyskać dostęp poprzez jego nazwę, jeśli nie chcesz mieszać funkcji i klas z twoimi

import util # imports util.py

util.clean()
util.setup(4)

lub możesz zaimportować funkcje i klasy do swojego kodu

from util import clean, setup
clean()
setup(4)

możesz użyć wildchar *, aby zaimportować wszystko z tego modułu do swojego kodu

from util import *
clean()
setup(4)
A.Zaben
źródło
10

W python3 nie__init__.py jest już konieczne . Jeśli bieżącym katalogiem konsoli jest katalog, w którym znajduje się skrypt Pythona, wszystko działa poprawnie

import user

Nie zadziała to jednak, jeśli zostanie wywołany z innego katalogu, który nie zawiera user.py.
W takim przypadku użyj

from . import user

Działa to nawet, jeśli chcesz zaimportować cały plik zamiast tylko stamtąd stamtąd.

lucidbrot
źródło
2
Korzystam z pylinta w kodzie vs i miałem problem z importem tego samego katalogu zawsze oznaczonym jako błąd ( import userpodkreślono na czerwono); zmieniono na względny import ( from . import user) i linijka już go nie oflagowała.
rbatt
9

Aby ułatwić zrozumienie:

Krok 1: przejdźmy do jednego katalogu, w którym wszystkie zostaną uwzględnione

$ cd /var/tmp

Krok 2: Teraz możemy utworzyć plik class1.py, który ma nazwę klasy Class1 z pewnym kodem

$ cat > class1.py <<\EOF
class Class1:
    OKBLUE = '\033[94m'
    ENDC = '\033[0m'
    OK = OKBLUE + "[Class1 OK]: " + ENDC
EOF

Krok 3: Teraz stwórzmy plik class2.py, który ma nazwę klasy Class2 z pewnym kodem

$ cat > class2.py <<\EOF
class Class2:
    OKBLUE = '\033[94m'
    ENDC = '\033[0m'
    OK = OKBLUE + "[Class2 OK]: " + ENDC
EOF

Krok 4: teraz pozwala stworzyć jeden main.py, który zostanie wykonany raz, aby użyć Class1 i Class2 z 2 różnych plików

$ cat > main.py <<\EOF
"""this is how we are actually calling class1.py and  from that file loading Class1"""
from class1 import Class1 
"""this is how we are actually calling class2.py and  from that file loading Class2"""
from class2 import Class2

print Class1.OK
print Class2.OK
EOF

Krok 5: Uruchom program

$ python main.py

Wynik byłby

[Class1 OK]: 
[Class2 OK]:
Hassan Nadeem
źródło
4
A co się stanie, jeśli to nie zadziała, a main.py nie może odczytać klasy 1 lub klasy 2? ... czego nam brakuje?
darkgaze
6

Python 3


Podobnie directory .

importować plik:log.py

Klasa import: SampleApp().

import log
if __name__ == "__main__":
    app = log.SampleApp()
    app.mainloop()

lub

katalog jest basic .

import do pliku: log.py .

Klasa import: SampleApp().

from basic import log
if __name__ == "__main__":
    app = log.SampleApp()
    app.mainloop()
Yasith Praharshana
źródło
5
from user import User 
from dir import Dir 
demas
źródło
Działa to dla mnie bez pliku inicjującego .py dla Python 2.7 i Python 3.6.
imsrgadich,
1
@ imrgadich działa tak długo, jak Python działa w katalogu zawierającym pliki. To jest wyjątek. Zobacz ten komentarz
Ciprian Tomoiagă
5

Jeśli user.py i dir.py nie obejmują klas, to

from .user import User
from .dir import Dir

nie działa. Następnie należy zaimportować jako

from . import user
from . import dir
Andreas Foteas
źródło
0

Nie jestem pewien, dlaczego to działa, ale przy użyciu kompilacji Pycharm from file_in_same_dir import class_name

IDE narzekało na to, ale wygląda na to, że nadal działało. Używam Python 3.7

żądło
źródło
-2

Po prostu zbyt krótko, Utwórz plik __init__.pyto katalog klas, a następnie zaimportuj go do skryptu w następujący sposób (Importuj całą wielkość liter)

from classes.myscript import *

Importuj tylko wybrane klasy

from classes.myscript import User
from classes.myscript import Dir
Shafiq
źródło
4
Import symboli wieloznacznych, jak widać w tej odpowiedzi, jest ogólnie uważany za zły styl, jak opisano w PEP 8 .
V02460
-3

importować z tego samego katalogu

from . import the_file_you_want_to_import 

aby zaimportować z podkatalogu, katalog powinien zawierać

init .py

wtedy plik inny niż ty

z katalogu zaimportuj swój plik

rojo_hlerr
źródło
3
Nie sądzę, aby ta odpowiedź dodała coś, czego nie udzieliły inne odpowiedzi, a także nie jest wyczerpującym podsumowaniem innych odpowiedzi. Zastanawiam się więc, dlaczego to napisałeś
lucidbrot
-3

Python3

posługiwać się

from .user import User inside dir.py file

i

use from class.dir import Dir inside main.py
or from class.usr import User inside main.py

lubię to

icharis
źródło
3
Ta odpowiedź tak naprawdę nie dodaje niczego więcej niż inna odpowiedź, którą już zrobiono, i nie ma wyjaśnienia. Czy istnieje sposób na edycję odpowiedzi w celu dodania lub ulepszenia? Bo w przeciwnym razie należy zanegować, tak jakby ta odpowiedź została lub została całkowicie usunięta.
Das_Geek,