Aynı dizinde veya alt dizinde sınıf nasıl alınır?


675

Tüm .py dosyalarını depolayan bir dizin var .

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

Ben sınıfları kullanmak istiyorum user.py ve dir.py içinde main.py .
Bu Python sınıflarını main.py'ye nasıl aktarabilirim ?
Dahası, nasıl sınıfını alabilirsiniz Usereğer user.py bir alt dizinde?

bin/
    dir.py
    main.py
    usr/
        user.py


Yanıtlar:


938

Python 2

__init__.pyDosyalarla aynı dizinde çağrılan boş bir dosya oluşturun . Bu, Python'a "bu dizinden içe aktarmanın uygun olduğunu" gösterecektir.

O zaman yap ...

from user import User
from dir import Dir

Aynı şey, dosyalar bir alt dizindeyse de geçerlidir - alt dizine bir __init__.pyde koyun ve ardından nokta gösterimiyle düzenli içe aktarma ifadeleri kullanın. Her dizin düzeyi için içe aktarma yoluna eklemeniz gerekir.

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

Dizin "sınıflar" olarak adlandırılmışsa, bunu yaparsınız:

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

Python 3

Önceki ile aynı, ancak .bir alt dizin kullanılmıyorsa modül adının başına bir önek ekleyin:

from .user import User
from .dir import Dir

14
Eğer __init__.pybir değil boş, o zaman ne varsa __init__.pypaketi içe (ve ithal değil şeyler zaman satışa sunulacak budur __init__.pyhiç kullanılamaz).
Amber

23
Neden bir __init__.pydosyaya ihtiyaç var? Her üç dosyayı da aynı dizine koyar ve çalıştırırsam main.py, importdiğer iki modülden onsuz da yapabilir. Neyi kaçırıyorum?
martineau

30
Çünkü Python içe aktarmanıza izin verilen dizinleri bu şekilde tanımlar. Çalıştırdığınız komut dosyasının dizini bir istisnadır - bundan her zaman içe aktarmanıza izin verilir.
Amber

20
@nbro & Amber: FWIW, sanırım __init__.pyaynı dizindeki diğer modülleri içe aktarabilme ve değiştirebilme konusunda ince bir şey değişti . Özellikle Python 2.7.8'de çalışan dosyanın kendisi ile importaynı dizindeki diğer modüllerin __init__.pyPython 3.4.1'de başarısız olması. Bunu düzeltmek için her birinin alt dizinin adını ve bir noktasını öneklemek import modulezorunda kaldım (yani olarak değiştirilmesi gerekiyordu import subdirectory.module). Neyse ki bunu yaptıktan sonra hala Python 2.7.8'de çalıştı.
martineau

4
Bu çözümün artık işlevsel olmadığını doğrulayabilirim. Düzeltmek, değiştirmek veya tamamen silmek isteyebilirsiniz.
Luís de Sousa

137

( Martineau'nun yorumu sayesinde ), aynı dizindeki dosyalardan sınıfları içe aktarmak için şimdi Python 3'e yazacağınızı öğrendim :

from .user import User
from .dir import Dir

8
bunu denerseniz hayır ben aşağıdaki hatayı alıyorum ValueError: Attempted relative import in non-packageama değiştirdiğim zaman hata giderfrom user import User
Korpel

.Fileloader import Fileloader kullanıyorum ve ImportError alıyorum: 'Fileloader' ismini alamıyorum
Frikster

3
@Korpel: stackoverflow.com/questions/11536764/… daki tartışmaların ardından, yukarıda verilen içe aktarma işleminin çalışıp çalışmadığına bağlı olduğunun farkına varıyorum: [1] betiğinizin nasıl adlandırıldığını (paket olarak ya da değil) [2] nerede asıl çalışma yolu yürüttüğünüzde [3] çalışma ortamınızın yol değişkeninin nasıl doldurulduğu
ecp

@Korpel: Bunu fark ettim. modül adından önce yalnızca init .py dosyası mevcutsa gereklidir . atlanabilir / çıkarılmalıdır.
MUG4N

39

Sizin main.py:

from user import Class

burada Classiçe aktarmak istediğiniz sınıfın adıdır.

Yöntemini Classçağırmak istiyorsanız, şunu kullanarak arayabilirsiniz:

Class.method

__init__.pyAynı dizinde boş bir dosya olması gerektiğini unutmayın .


1
İçe aktarmaya çalıştığınız modülün sınıfı yoksa ne yaparsınız? Sadece ham fonksiyonlar? Python 2'de tek yapmam gereken 'içe aktarma modülü' idi. Python 3'te çalışmaz, 'import .module' de çalışmaz
Frikster

2
Bu, silindikten sonra python3 içinde çalışır __init__.py.
motor gücü

13

İşlevleri ve sınıfları kendinizle karıştırmak istemiyorsanız modülü içe aktarabilir ve adıyla erişebilirsiniz.

import util # imports util.py

util.clean()
util.setup(4)

veya işlevleri ve sınıfları kodunuza aktarabilirsiniz

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

bu modüldeki her şeyi kodunuza aktarmak için wildchar * kullanabilirsiniz

from util import *
clean()
setup(4)

10

Python3 olarak, __init__.pyolduğu artık gerekli . Konsolun geçerli dizini python betiğinin bulunduğu dizinse, her şey düzgün çalışır

import user

Ancak, içermeyen farklı bir dizinden çağrılırsa bu çalışmaz user.py.
Bu durumda,

from . import user

Bu, yalnızca bir sınıf yerine tüm dosyayı içe aktarmak isteseniz bile çalışır.


2
Pylint vs kodunu kullanıyorum ve aynı dizin alma her zaman bir hata olarak işaretlenmiş ( import userkırmızı altı çizili) ile sorun yaşıyordu ; göreli içe aktarma ( from . import user) olarak değiştirildi ve linter artık onu işaretlemedi.
rbatt

9

Anlamayı daha kolay hale getirmek için:

Adım 1: Her şeyin dahil edileceği bir dizine gidelim

$ cd /var/tmp

2.Adım: Şimdi bazı kodlarla Class1 sınıf adına sahip bir class1.py dosyası yapalım

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

Adım 3: Şimdi bazı kodlarla Class2 sınıf adına sahip bir class2.py dosyası yapalım

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

Adım 4: Şimdi 2 farklı dosyadan Class1 ve Class2'yi kullanmak için bir kez çalıştırılacak bir main.py yapalım

$ 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

Adım 5: Programı çalıştırın

$ python main.py

Çıktı

[Class1 OK]: 
[Class2 OK]:

4
Ve eğer bu işe yaramazsa ve main.py sınıf1 veya sınıf2'yi okuyamazsa ne olur? ... neyi kaçırıyoruz?
darkgaze

6

Python 3


Aynı directory.

önemli dosya:log.py

ithalat sınıfı SampleApp().

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

veya

dizin basic.

dosyada içe: log.py.

ithalat sınıfı SampleApp().

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

5
from user import User 
from dir import Dir 

Bu kalmadan benim için çalıştı init hem Python 2.7 ve Python 3.6 için .py dosyasını.
imsrgadich

1
@imsrgadich dosyaları içeren dizinde python çalıştırdığınız sürece çalışır. Bu bir istisna. Bu yorumu
Ciprian Tomoiagă

5

User.py ve dir.py sınıfları içermiyorsa

from .user import User
from .dir import Dir

çalışmıyor. Daha sonra şu şekilde içe aktarmalısınız:

from . import user
from . import dir

0

Neden bu işten emin değilim ama Pycharm derlemesini kullanıyorum from file_in_same_dir import class_name

IDE bu konuda şikayetçi oldu ama hala işe yarıyor gibi görünüyor. Python 3.7 kullanıyorum


-2

Sadece çok kısa, Dosya oluştur __init__.pysınıflar dizinidir ve aşağıdaki gibi betiğinize aktarın (Tüm vakaları içe aktar)

from classes.myscript import *

Yalnızca seçili sınıfları içe aktar

from classes.myscript import User
from classes.myscript import Dir

4
Bu cevapta görüldüğü gibi joker karakter ithalatı genellikle PEP 8'de açıklandığı gibi kötü stil olarak kabul edilir .
V02460

-3

aynı dizinden içe aktarmak için

from . import the_file_you_want_to_import 

dizinin içerdiği alt dizinden içe aktarmak için

init .py

sizden başka bir dosya

dizinden ithalat dosya_dosyası


3
Bu cevabın diğer cevapların vermediği bir şey kattığını düşünmüyorum ve aynı zamanda diğer cevapların kapsamlı bir özeti de değil. Neden yazdığını merak ediyorum
lucidbrot

-3

Python3

kullanım

from .user import User inside dir.py file

ve

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

böyle


3
Bu cevap diğer cevaptan daha fazla bir şey eklemiyor ve hiçbir açıklaması yok. Cevabınızı eklemek veya geliştirmek için cevabınızı düzenlemenin bir yolu var mı ? Aksi halde, bu cevap tamamen kaldırılmış veya kaldırılmış gibi reddedilmiştir .
Das_Geek
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.