Menurut komentar di bawah ini oleh @Rob_before_edits dan thread stackoverflow ini 37139786 , tampaknya init .py tidak lagi diperlukan untuk Python 3.3+.
Python mendefinisikan dua jenis paket, paket reguler dan paket namespace. Paket reguler adalah paket tradisional seperti yang ada di Python 3.2 dan sebelumnya. Paket reguler biasanya diimplementasikan sebagai direktori yang berisi __init__.pyfile. Ketika paket reguler diimpor, __init__.pyfile ini secara implisit dieksekusi, dan objek yang didefinisikannya terikat dengan nama-nama dalam namespace paket. The __init__.pyFile dapat berisi kode Python yang sama bahwa setiap modul lainnya dapat berisi, dan Python akan menambahkan beberapa atribut tambahan untuk modul ketika diimpor.
Tapi cukup klik tautannya, itu berisi contoh, informasi lebih lanjut, dan penjelasan tentang paket namespace, jenis paket tanpa itu __init__.py.
Apa artinya ini: "ini dilakukan untuk mencegah direktori dengan nama umum, seperti string, dari menyembunyikan modul yang valid secara tidak sengaja yang terjadi kemudian pada jalur pencarian modul"?
Carl G
97
@CarlG Python mencari daftar direktori untuk menyelesaikan nama, misalnya, pernyataan impor. Karena ini bisa berupa direktori apa saja, dan yang sewenang-wenang dapat ditambahkan oleh pengguna akhir, pengembang harus khawatir tentang direktori yang kebetulan berbagi nama dengan modul Python yang valid, seperti 'string' dalam contoh dokumen. Untuk meringankan ini, ia mengabaikan direktori yang tidak mengandung file bernama _ _ init _ _.py (tanpa spasi), bahkan jika itu kosong.
Alchemist Dua-Bit
186
@CarlG Coba ini. Buat direktori yang disebut 'datetime' dan di dalamnya buat dua file kosong, file init.py (dengan garis bawah) dan datetime.py. Sekarang buka interpreter, import sys, dan issue sys.path.insert(0, '/path/to/datetime'), ganti path itu dengan path ke direktori apa pun yang baru saja Anda buat. Sekarang coba sesuatu seperti from datetime import datetime;datetime.now(). Anda harus mendapatkan AttributeError (karena mengimpor file kosong Anda sekarang). Jika Anda mengulangi langkah-langkah ini tanpa membuat file init kosong, ini tidak akan terjadi. Itulah yang dimaksudkan untuk dicegah.
Alchemist Dua-Bit
4
@ DarekNędza Anda telah memasang sesuatu yang salah jika Anda tidak bisa membuka juru bahasa Python dan mengeluarkannya from datetime import datetimetanpa kesalahan. Itu bagus sepanjang perjalanan kembali ke versi 2.3!
File yang diberi nama __init__.pydigunakan untuk menandai direktori pada disk sebagai direktori paket Python. Jika Anda memiliki file
mydir/spam/__init__.py
mydir/spam/module.py
dan mydirada di jalur Anda, Anda dapat mengimpor kode module.pysebagai
import spam.module
atau
from spam import module
Jika Anda menghapus __init__.pyfile, Python tidak akan lagi mencari submodul di dalam direktori itu, sehingga upaya untuk mengimpor modul akan gagal.
The __init__.pyfile biasanya kosong, tetapi dapat digunakan untuk mengekspor bagian yang dipilih dari paket dengan nama yang lebih nyaman, fungsi kenyamanan ditahan, dll Mengingat contoh di atas, isi modul init dapat diakses sebagai
Pembaruan: File __init__.pydiperlukan di bawah Python 2.X dan masih diperlukan di bawah Python 2.7.12 (saya mengujinya) tetapi tidak lagi diperlukan dari (diduga) Python 3.3 dan seterusnya, dan tidak diperlukan di bawah Python 3.4.3 (I mengujinya). Lihat stackoverflow.com/questions/37139786 untuk lebih jelasnya.
Rob_before_edits
4
Jangan gunakan itu. Ini adalah paket "namespace", bukan paket biasa. paket namespace digunakan untuk kasus penggunaan yang sangat jarang. Anda mungkin tidak perlu tahu kapan menggunakannya. Gunakan saja __init__.py.
metana
2
Namun jika Anda memiliki setup.pydan menggunakannya find_packages()perlu ada __init__.pydi setiap direktori. Lihat stackoverflow.com/a/56277323/7127824
techkuz
484
Selain memberi label pada direktori sebagai paket Python dan mendefinisikan __all__, __init__.pymemungkinkan Anda untuk mendefinisikan variabel apa pun di tingkat paket. Melakukannya sering kali nyaman jika suatu paket mendefinisikan sesuatu yang akan sering diimpor, dengan cara seperti API. Pola ini mempromosikan kepatuhan pada filosofi "flat lebih baik daripada bersarang" dari Pythonic.
Sebuah contoh
Berikut adalah contoh dari salah satu proyek saya, di mana saya sering mengimpor sessionmakerdisebut Sessionuntuk berinteraksi dengan database saya. Saya menulis paket "database" dengan beberapa modul:
import os
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
engine = create_engine(os.environ['DATABASE_URL'])Session= sessionmaker(bind=engine)
Karena saya mendefinisikan di Sessionsini, saya dapat memulai sesi baru menggunakan sintaksis di bawah ini. Kode ini akan sama dieksekusi dari dalam atau di luar direktori paket "database".
from database importSession
session =Session()
Tentu saja, ini adalah kenyamanan kecil - alternatifnya adalah dengan mendefinisikan Sessiondalam file baru seperti "create_session.py" dalam paket database saya, dan mulai sesi baru menggunakan:
from database.create_session importSession
session =Session()
Bacaan lebih lanjut
Ada thread reddit yang cukup menarik yang mencakup penggunaan yang sesuai di __init__.pysini:
engine, sessionmaker, create_engine, Dan ossemua bisa juga diimpor dari databasesekarang ... sepertinya Anda telah membuat berantakan namespace itu.
ArtOfWarfare
9
@ArtOfWarfare, Anda dapat menggunakan __all__ = [...]untuk membatasi apa yang diimpor dengan import *. Tapi selain dari itu, ya, Anda memiliki namespace tingkat atas yang berantakan.
Nathan Gould
Bolehkah saya tahu apa itu 'URL DATABASE'? Saya mencoba mereplikasi ini dengan melampirkan create_engine dengan 'mysql + mysqldb: // root: python @ localhost: 3306 / test' tetapi tidak berhasil. Terima kasih.
SunnyBoiz
2
Bagaimana Anda mengakses kelas 'Sesi' yang didefinisikan dalam init dari paket di dalam misalnya quieries.py?
vldbnc
253
Ada 2 alasan utama __init__.py
Untuk kenyamanan: pengguna lain tidak perlu mengetahui lokasi pasti fungsi Anda di hierarki paket Anda.
oh, sebelum membaca jawaban Anda, saya pikir memanggil fungsi secara eksplisit dari lokasinya adalah praktik yang baik.
Aerin
2
@ Aerin akan lebih baik jangan menganggap pernyataan pendek (atau, dalam hal ini, kesimpulan subyektif) selalu benar. Mengimpor dari __init__.pyterkadang bermanfaat, tetapi tidak setiap saat.
Tobias Sette
2
Apakah kode ini dieksekusi pada waktu impor atau runtime?
user1559897
111
The __init__.pyFile membuat Python memperlakukan direktori yang berisi sebagai modul.
Selanjutnya, ini adalah file pertama yang dimuat dalam modul, sehingga Anda dapat menggunakannya untuk mengeksekusi kode yang ingin Anda jalankan setiap kali modul dimuat, atau menentukan submodul yang akan diekspor.
Dukungan asli untuk direktori paket yang tidak memerlukan __init__.pyfile penanda dan dapat secara otomatis menjangkau banyak segmen jalur (terinspirasi oleh berbagai pendekatan pihak ketiga untuk paket namespace, seperti dijelaskan dalam PEP 420 )
Dalam Python definisi paket sangat sederhana. Seperti Java, struktur hierarkis dan struktur direktori adalah sama. Tetapi Anda harus memiliki __init__.pysatu paket. Saya akan menjelaskan __init__.pyfile dengan contoh di bawah ini:
__init__.pybisa kosong, asalkan ada. Ini menunjukkan bahwa direktori harus dianggap sebagai paket. Tentu saja, __init__.pybisa juga mengatur konten yang sesuai.
Jika kita menambahkan fungsi di module_n1:
def function_X():print"function_X in module_n1"return
Setelah berlari:
>>>from package_x.subPackage_b.module_n1 import function_X
>>>function_X()
function_X in module_n1
Kemudian kami mengikuti paket hierarki dan memanggil module_n1 fungsinya. Kita dapat menggunakan __init__.pydi subPackage_b seperti ini:
__all__ =['module_n2','module_n3']
Setelah berlari:
>>>from package_x.subPackage_b import*>>>module_n1.function_X()Traceback(most recent call last):File"<stdin>", line 1,in<module>ImportError:No module named module_n1
Oleh karena itu menggunakan * impor, paket modul tergantung pada __init__.pykonten.
Bagaimana setup.py saya terlihat melakukan impor yang sama melalui perpustakaan paket? from package_x.subPackage_b.module_n1 import function_X
technazi
jadi kunci mengambil di sini adalah "menggunakan * impor, paket modul tunduk pada konten init .py"
Minnie
54
Meskipun Python bekerja tanpa __init__.pyfile, Anda tetap harus memasukkannya.
Ini menentukan paket harus diperlakukan sebagai modul, jadi karena itu sertakan (bahkan jika itu kosong).
Ada juga kasus di mana Anda sebenarnya dapat menggunakan __init__.pyfile:
Bayangkan Anda memiliki struktur file berikut:
main_methods
|- methods.py
Dan methods.pyberisi ini:
def foo():return'foo'
Untuk menggunakan foo()Anda perlu salah satu dari yang berikut:
from main_methods.methods import foo # Call with foo()from main_methods import methods # Call with methods.foo()import main_methods.methods # Call with main_methods.methods.foo()
Mungkin di sana Anda perlu (atau ingin) untuk tetap methods.pydi dalam main_methods(runtimes / dependensi misalnya) tetapi Anda hanya ingin mengimpor main_methods.
Jika Anda mengubah nama methods.pyuntuk __init__.pymaka Anda dapat menggunakan foo()hanya dengan mengimpor main_methods:
import main_methods
print(main_methods.foo())# Prints 'foo'
Ini berfungsi karena __init__.pydiperlakukan sebagai bagian dari paket.
Beberapa paket Python sebenarnya melakukan ini. Contohnya adalah dengan JSON , di mana menjalankan import jsonsebenarnya mengimpor __init__.pydari jsonpaket ( lihat struktur file paket di sini ):
Ini memfasilitasi mengimpor file python lainnya. Ketika Anda menempatkan file ini di direktori (katakan hal-hal) yang berisi file py lainnya, maka Anda dapat melakukan sesuatu seperti mengimpor barang.other.
root\
stuff\
other.py
morestuff\
another.py
Tanpa ini __init__.pydi dalam hal-hal direktori, Anda tidak dapat mengimpor other.py, karena Python tidak tahu di mana kode sumber untuk barang-barang itu dan tidak dapat mengenalinya sebagai paket.
Saya memiliki struktur yang sama dalam proyek saya (python 3.4) tetapi saya tidak dapat membuat another.py melihat other.py. Bagaimana saya harus melakukan impor? dari root.stuff impor lainnya? Ini bekerja dalam mode debug VSCode tetapi tidak dalam baris perintah. Ada ide?
rodrigorf
10
Sebuah __init__.pyfile yang membuat impor mudah. Ketika sebuah __init__.pyhadir dalam suatu paket, fungsi a()dapat diimpor dari file b.pyseperti:
from b import a
Tanpa itu, Anda tidak dapat mengimpor secara langsung. Anda harus mengubah jalur sistem:
import sys
sys.path.insert(0,'path/to/b.py')from b import a
apa maksud Anda " fungsi a () dapat diimpor dari file b.py [snippet] Tanpa itu, Anda tidak dapat mengimpor secara langsung. "? Saya dapat mengimpor fungsi a () dari file b.py tanpa __init__.py.
Jawaban:
Ini digunakan untuk menjadi bagian yang diperlukan dari sebuah paket ( lama, pra-3.3 "paket reguler" , bukan 3.3 "paket namespace" yang lebih baru ).
Berikut dokumentasinya.
Tapi cukup klik tautannya, itu berisi contoh, informasi lebih lanjut, dan penjelasan tentang paket namespace, jenis paket tanpa itu
__init__.py
.sumber
sys.path.insert(0, '/path/to/datetime')
, ganti path itu dengan path ke direktori apa pun yang baru saja Anda buat. Sekarang coba sesuatu sepertifrom datetime import datetime;datetime.now()
. Anda harus mendapatkan AttributeError (karena mengimpor file kosong Anda sekarang). Jika Anda mengulangi langkah-langkah ini tanpa membuat file init kosong, ini tidak akan terjadi. Itulah yang dimaksudkan untuk dicegah.from datetime import datetime
tanpa kesalahan. Itu bagus sepanjang perjalanan kembali ke versi 2.3!builtins
daftar fungsi dan kelas built-in, bukan modul built-in (lih. Docs.python.org/3/tutorial/modules.html#the-dir-function ). Jika Anda ingin daftar modul bawaan , lakukanimport sys; print(sys.builtin_module_names)
(lih. Docs.python.org/3/library/sys.html#sys.builtin_module_names ).File yang diberi nama
__init__.py
digunakan untuk menandai direktori pada disk sebagai direktori paket Python. Jika Anda memiliki filedan
mydir
ada di jalur Anda, Anda dapat mengimpor kodemodule.py
sebagaiatau
Jika Anda menghapus
__init__.py
file, Python tidak akan lagi mencari submodul di dalam direktori itu, sehingga upaya untuk mengimpor modul akan gagal.The
__init__.py
file biasanya kosong, tetapi dapat digunakan untuk mengekspor bagian yang dipilih dari paket dengan nama yang lebih nyaman, fungsi kenyamanan ditahan, dll Mengingat contoh di atas, isi modul init dapat diakses sebagaiberdasarkan ini
sumber
__init__.py
diperlukan di bawah Python 2.X dan masih diperlukan di bawah Python 2.7.12 (saya mengujinya) tetapi tidak lagi diperlukan dari (diduga) Python 3.3 dan seterusnya, dan tidak diperlukan di bawah Python 3.4.3 (I mengujinya). Lihat stackoverflow.com/questions/37139786 untuk lebih jelasnya.__init__.py
.setup.py
dan menggunakannyafind_packages()
perlu ada__init__.py
di setiap direktori. Lihat stackoverflow.com/a/56277323/7127824Selain memberi label pada direktori sebagai paket Python dan mendefinisikan
__all__
,__init__.py
memungkinkan Anda untuk mendefinisikan variabel apa pun di tingkat paket. Melakukannya sering kali nyaman jika suatu paket mendefinisikan sesuatu yang akan sering diimpor, dengan cara seperti API. Pola ini mempromosikan kepatuhan pada filosofi "flat lebih baik daripada bersarang" dari Pythonic.Sebuah contoh
Berikut adalah contoh dari salah satu proyek saya, di mana saya sering mengimpor
sessionmaker
disebutSession
untuk berinteraksi dengan database saya. Saya menulis paket "database" dengan beberapa modul:Saya
__init__.py
berisi kode berikut:Karena saya mendefinisikan di
Session
sini, saya dapat memulai sesi baru menggunakan sintaksis di bawah ini. Kode ini akan sama dieksekusi dari dalam atau di luar direktori paket "database".Tentu saja, ini adalah kenyamanan kecil - alternatifnya adalah dengan mendefinisikan
Session
dalam file baru seperti "create_session.py" dalam paket database saya, dan mulai sesi baru menggunakan:Bacaan lebih lanjut
Ada thread reddit yang cukup menarik yang mencakup penggunaan yang sesuai di
__init__.py
sini:http://www.reddit.com/r/Python/comments/1bbbwk/whats_your_opinion_on_what_to_include_in_init_py/
Pendapat mayoritas tampaknya bahwa
__init__.py
file harus sangat tipis untuk menghindari melanggar filosofi "eksplisit lebih baik daripada implisit".sumber
engine
,sessionmaker
,create_engine
, Danos
semua bisa juga diimpor daridatabase
sekarang ... sepertinya Anda telah membuat berantakan namespace itu.__all__ = [...]
untuk membatasi apa yang diimpor denganimport *
. Tapi selain dari itu, ya, Anda memiliki namespace tingkat atas yang berantakan.Ada 2 alasan utama
__init__.py
Untuk kenyamanan: pengguna lain tidak perlu mengetahui lokasi pasti fungsi Anda di hierarki paket Anda.
kemudian orang lain dapat memanggil add () oleh
tanpa mengetahui file1, suka
Jika Anda ingin sesuatu diinisialisasi; misalnya, pencatatan (yang harus diletakkan di tingkat atas):
sumber
__init__.py
terkadang bermanfaat, tetapi tidak setiap saat.The
__init__.py
File membuat Python memperlakukan direktori yang berisi sebagai modul.Selanjutnya, ini adalah file pertama yang dimuat dalam modul, sehingga Anda dapat menggunakannya untuk mengeksekusi kode yang ingin Anda jalankan setiap kali modul dimuat, atau menentukan submodul yang akan diekspor.
sumber
Sejak Python 3.3,
__init__.py
tidak lagi diperlukan untuk mendefinisikan direktori sebagai paket Python yang dapat diimpor.Periksa PEP 420: Paket Namespace Tersirat :
Inilah tesnya:
referensi:
https://docs.python.org/3/whatsnew/3.3.html#pep-420-implicit-namespace-packages
https://www.python.org/dev/peps/pep-0420/
Apakah __init__. py tidak diperlukan untuk paket di Python 3?
sumber
Dalam Python definisi paket sangat sederhana. Seperti Java, struktur hierarkis dan struktur direktori adalah sama. Tetapi Anda harus memiliki
__init__.py
satu paket. Saya akan menjelaskan__init__.py
file dengan contoh di bawah ini:__init__.py
bisa kosong, asalkan ada. Ini menunjukkan bahwa direktori harus dianggap sebagai paket. Tentu saja,__init__.py
bisa juga mengatur konten yang sesuai.Jika kita menambahkan fungsi di module_n1:
Setelah berlari:
Kemudian kami mengikuti paket hierarki dan memanggil module_n1 fungsinya. Kita dapat menggunakan
__init__.py
di subPackage_b seperti ini:Setelah berlari:
Oleh karena itu menggunakan * impor, paket modul tergantung pada
__init__.py
konten.sumber
from package_x.subPackage_b.module_n1 import function_X
Meskipun Python bekerja tanpa
__init__.py
file, Anda tetap harus memasukkannya.Ini menentukan paket harus diperlakukan sebagai modul, jadi karena itu sertakan (bahkan jika itu kosong).
Ada juga kasus di mana Anda sebenarnya dapat menggunakan
__init__.py
file:Bayangkan Anda memiliki struktur file berikut:
Dan
methods.py
berisi ini:Untuk menggunakan
foo()
Anda perlu salah satu dari yang berikut:Mungkin di sana Anda perlu (atau ingin) untuk tetap
methods.py
di dalammain_methods
(runtimes / dependensi misalnya) tetapi Anda hanya ingin mengimpormain_methods
.Jika Anda mengubah nama
methods.py
untuk__init__.py
maka Anda dapat menggunakanfoo()
hanya dengan mengimpormain_methods
:Ini berfungsi karena
__init__.py
diperlakukan sebagai bagian dari paket.Beberapa paket Python sebenarnya melakukan ini. Contohnya adalah dengan JSON , di mana menjalankan
import json
sebenarnya mengimpor__init__.py
darijson
paket ( lihat struktur file paket di sini ):sumber
__init__.py
akan memperlakukan direktori itu sebagai modul yang dapat dimuat.Untuk orang-orang yang lebih suka membaca kode, saya menaruh komentar Two-Bit Alchemist di sini.
sumber
Ini memfasilitasi mengimpor file python lainnya. Ketika Anda menempatkan file ini di direktori (katakan hal-hal) yang berisi file py lainnya, maka Anda dapat melakukan sesuatu seperti mengimpor barang.other.
Tanpa ini
__init__.py
di dalam hal-hal direktori, Anda tidak dapat mengimpor other.py, karena Python tidak tahu di mana kode sumber untuk barang-barang itu dan tidak dapat mengenalinya sebagai paket.sumber
Sebuah
__init__.py
file yang membuat impor mudah. Ketika sebuah__init__.py
hadir dalam suatu paket, fungsia()
dapat diimpor dari fileb.py
seperti:Tanpa itu, Anda tidak dapat mengimpor secara langsung. Anda harus mengubah jalur sistem:
sumber