__İnit__.py Python 3.3 ve sonraki sürümleri için gerekli değildir


195

Python 3.5.1 kullanıyorum. Belgeyi ve paket bölümünü burada okudum: https://docs.python.org/3/tutorial/modules.html#packages

Şimdi, aşağıdaki yapıya sahibim:

/home/wujek/Playground/a/b/module.py

module.py:

class Foo:
    def __init__(self):
        print('initializing Foo')

Şimdi ise /home/wujek/Playground:

~/Playground $ python3
>>> import a.b.module
>>> a.b.module.Foo()
initializing Foo
<a.b.module.Foo object at 0x100a8f0b8>

Benzer şekilde, şimdi evde, süper klasör Playground:

~ $ PYTHONPATH=Playground python3
>>> import a.b.module
>>> a.b.module.Foo()
initializing Foo
<a.b.module.Foo object at 0x10a5fee10>

Aslında her türlü şeyi yapabilirim:

~ $ PYTHONPATH=Playground python3
>>> import a
>>> import a.b
>>> import Playground.a.b

Bu neden işe yarıyor? Python yolu klasöre işaret ettiğinde __init__.pyhem de (hem boş olanları işe yarayacak) dosyaları olması gerekiyordu ave ithal biçin module.pygerekli olsa Playground?

Bu Python 2.7'den değişmiş gibi görünüyor:

~ $ PYTHONPATH=Playground python
>>> import a
ImportError: No module named a
>>> import a.b
ImportError: No module named a.b
>>> import a.b.module
ImportError: No module named a.b.module

İle __init__.pyhem de ~/Playground/ave ~/Playground/a/bo cezayı çalışır.

Yanıtlar:


192

Python 3.3+, dosyasız paketler oluşturmasına izin veren Örtülü Ad Alanı Paketleri içerir __init__.py.

Örtülü ad alanı paketlerine izin vermek, bir __init__.pydosya sağlama gereksiniminin tamamen bırakılabileceği ve etkilenebileceği anlamına gelir ....

__init__.pyDosyalarla eski yol hala Python 2'deki gibi çalışır.


10
Belgeyi okuyacağım, ama biraz uzun. Hızlı bir şekilde özetlemek mümkün mü? Bana söyleyebilir misiniz: hala init .py'yi destekliyor mu yoksa tamamen yok sayar mı? Onları destekliyorsa, işlevsellikteki fark nedir ve neden bu ikilik?
wujek

3
Bu yüzden öğretici muhtemelen güncellenmelidir. Bunun için bir dokümantasyon hatası açıldı mı?
Michel Samia

4
Hala bu Zen Of Python çizgiyi 2 Explicit is better than implicit.
bozduğuna üzüldüm

5
@JayRizzo Ama: "Her ne kadar pratiklik saflığı aşıyor."
Mike Müller

19
@JayRizzo IMO daha da açık. Bazen init şeyler yapmak bazen olur __init__.py. Python 3 bu şeyler gerektiğinde __init__.pybelirli bir kod ile yeni bir oluşturmak , aksi takdirde yok. Bu, hangi paketlerin özel init'e sahip olduğunu görsel olarak bilmek kullanışlı olur. Bunun yerine python 2'ye her zaman bir __init__.py(genellikle boş) yerleştirmeliyim, çok sayıda yapmalıyım ve nihayet init kodunuzu nereye yerleştirdiğinizi hatırlamak daha zor. Bu da "Bir tane olmalı - ve tercihen sadece bir tane olmalıdır - bunu yapmanın açık bir yolu".
Paolo

148

ÖNEMLİ

@ Mike'ın cevabı doğru ama çok kesin değil. Python 3.3+ 'ün dosyasız bir paket oluşturmasına izin veren Örtülü Ad Alanı Paketlerini desteklediği doğrudur __init__.py.

Ancak bu SADECE EMPTY__init__.py dosyaları için geçerlidir . Dolayısıyla EMPTY__init__.py dosyaları artık gerekli değildir ve atlanabilir. Paket veya modüllerinden veya alt paketlerinden herhangi biri içe aktarılırken belirli bir başlatma komut dosyası çalıştırmak istiyorsanız, yine de bir __init__.pydosyaya ihtiyacınız vardır. Bu, neden herhangi bir şekilde yararlı olduğunu merak ediyorsanız, neden daha fazla başlatma yapmak için bir dosya kullanmak istediğinize dair harika bir Stack Overflow cevabıdır__init__.py .

Dizin Yapısı Örneği:

  parent_package/
     __init__.py            <- EMPTY, NOT NECESSARY in Python 3.3+
     child_package/
          __init__.py       <- STILL REQUIRED if you want to run an initialization script
          child1.py
          child2.py
          child3.py

parent_package/child_package/__init__.py:

print("from parent")

ÖRNEKLER

Aşağıdaki örnekler child_package, modüllerinden biri veya biri içe aktarıldığında başlatma komut dosyasının nasıl yürütüldüğünü gösterir .

Örnek 1 :

from parent_package import child_package  # prints "from parent"

Örnek 2 :

from parent_package.child_package import child1  # prints "from parent"

2
Ben olduğunu varsayalım run_script.pyaynı Dir parent_packageyüzden sadece gibi alabilirsiniz from parent_package.child_package import child1olmadan __init__.py?
mrgloom

Bunun amacı child_.py dosyasında some_function tanımlanmış olsa bile child_package.some_function yazabilmeniz mi? Başka bir deyişle, kullanıcının child_package içindeki farklı dosyalar hakkında bilgi sahibi olmasını gerektirmez. ?
johnbakers

Yaptığınız neden Evet, ben alamadım child1.py, child2.pysadece bir araya kodlarını koyarak yerine __init__doğrudan .py.
binki

İthalat beyanları __init__göreceli ithalat olmamalı mıydı yani from . import child1? Mutlak ithalat bana ModuleNotFoundError(Python 3.6'da) veriyor
Halbeard

5
Deneyimlerime göre, python 3.3+ ile bile, __init__.pybazen bir alt klasörü paket olarak adlandırmak istediğinizde olduğu gibi, yine de boş bir yere ihtiyaç vardır. Örneğin, çalıştırırsam test klasörünün altında python -m test.fooboş bir tane oluşturana kadar çalışmadı __init__.py. Ve burada 3.6.6 sürümü hakkında konuşuyorum!
Prahlad Yeri

7

Eğer varsa setup.pyprojenizde ve kullanmak find_packages()içindeki, bir olması gerekir __init__.pypaketleri otomatik olarak bulunabilmesi için her dizinine.

Paketler yalnızca bir __init__.pydosya içeriyorsa tanınır

UDP : Eğer olmadan örtülü ad paketlerini kullanmak istiyorsanız __init__.pysize sadece kullanmak zorunda find_namespace_packages()yerine

Dokümanlar


1

Biri __init__.pysadece örtülü ad alanı paketine sahip olmak istiyorsa atlamalı gerektiğini söyleyebilirim . Ne anlama geldiğini bilmiyorsanız, muhtemelen istemezsiniz ve bu nedenle __init__.pyPython 3'te bile kullanmaya devam etmelisiniz .

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.