__Init__.py के लिए क्या है?


2333

__init__.pyपायथन स्रोत निर्देशिका में क्या है ?


16
नीचे @Rob_before_edits और इस स्टैकओवरफ़्लो थ्रेड 37139786 द्वारा टिप्पणी के अनुसार , ऐसा लगता है कि init .py को अब पायथन 3.3+ की आवश्यकता नहीं है।
जून 15११

जवाबों:


1452

यह पैकेज का एक आवश्यक हिस्सा हुआ करता था ( पुराना, प्री-3.3 "रेगुलर पैकेज" , न कि नया 3.3+ "नेमस्पेस पैकेज" )।

यहाँ प्रलेखन है।

पायथन दो प्रकार के पैकेज, नियमित पैकेज और नेमस्पेस पैकेज को परिभाषित करता है। नियमित पैकेज पारंपरिक पैकेज हैं क्योंकि वे पायथन 3.2 और पूर्व में मौजूद थे। एक नियमित पैकेज को आमतौर पर एक निर्देशिका के रूप में लागू किया जाता है जिसमें एक __init__.pyफ़ाइल होती है। जब एक नियमित पैकेज आयात किया जाता है, तो यह __init__.pyफ़ाइल अंतर्निहित रूप से निष्पादित होती है, और इसे परिभाषित करने वाली वस्तुएं पैकेज के नामों में नामों से बंधी होती हैं। __init__.pyफ़ाइल एक ही अजगर कोड है कि किसी भी अन्य मॉड्यूल शामिल कर सकते हैं शामिल कर सकते हैं, और जब यह आयात किया जाता है पायथन मॉड्यूल के लिए कुछ अतिरिक्त विशेषताओं को जोड़ने जाएगा।

लेकिन बस लिंक पर क्लिक करें, इसमें एक उदाहरण, अधिक जानकारी और नाम स्थान पैकेज की व्याख्या, बिना पैकेज के प्रकार शामिल हैं __init__.py


187
इसका क्या मतलब है: "यह एक सामान्य नाम के साथ निर्देशिकाओं को रोकने के लिए किया जाता है, जैसे कि स्ट्रिंग, अनजाने में वैध मॉड्यूल को छुपाने से जो मॉड्यूल खोज पथ पर बाद में होता है"?
कार्ल जी

97
@CarlG Python निर्देशिकाओं की एक सूची खोजता है , जैसे कि नाम, उदाहरणों को आयात करने के लिए। क्योंकि ये कोई भी निर्देशिका हो सकती हैं, और अंत उपयोगकर्ता द्वारा मनमाने तरीके से जोड़े जा सकते हैं, डेवलपर्स को उन निर्देशिकाओं के बारे में चिंता करनी होगी जो एक मान्य पायथन मॉड्यूल के साथ नाम साझा करने के लिए होती हैं, जैसे डॉक्स उदाहरण में 'स्ट्रिंग'। इसे कम करने के लिए, यह उन निर्देशिकाओं को अनदेखा करता है जिनमें _ _ init _ _.py (कोई रिक्त स्थान) नाम की फ़ाइल नहीं होती है, भले ही वह रिक्त हो।
टू-बिट अल्केमिस्ट

186
@CarlG यह कोशिश करो। 'डेटाइम' नामक एक निर्देशिका बनाएं और इसमें दो रिक्त फाइलें, init.py फ़ाइल (अंडरस्कोर के साथ) और डेटाइमटाइम बनायें। अब एक दुभाषिया खोलें, आयात करें, और जारी करें sys.path.insert(0, '/path/to/datetime'), उस पथ को उस पथ के साथ प्रतिस्थापित करें जो आपने अभी-अभी जो भी निर्देशिका बनाई है। अब जैसे कुछ कोशिश करो from datetime import datetime;datetime.now()। आपको एक एट्रीब्यूट (क्योंकि यह अभी आपकी खाली फ़ाइल आयात कर रहा है) मिलना चाहिए। यदि आप रिक्त इनिट फ़ाइल बनाए बिना इन चरणों को दोहराते हैं, तो ऐसा नहीं होगा। इसे रोकने का इरादा है।
दो-बिट अल्केमिस्ट

4
@ DarekN Ddza आप गलत तरीके से सेट हो गए हैं अगर आप सिर्फ पायथन दुभाषिया नहीं खोल सकते हैं और from datetime import datetimeत्रुटि के बिना जारी कर सकते हैं । यह 2.3 संस्करण के लिए सभी तरह से अच्छा है!
दो-बिट अल्केमिस्ट

5
@Sang: यह गलत है: builtinsबिल्ट-इन फ़ंक्शन और क्लासेस , बिल्ट-इन मॉड्यूल नहीं (cf. docs.python.org/3/tutorial/modules.html#the-dir-function )। यदि आप अंतर्निहित मॉड्यूल सूचीबद्ध करना चाहते हैं , तो import sys; print(sys.builtin_module_names)(cf. docs.python.org/3/library/sys.html#sys.builtin_module_names ) करें।
मैगीयरो

842

नामित फ़ाइलों __init__.pyका उपयोग डिस्क पर निर्देशिकाओं को पायथन पैकेज निर्देशिकाओं के रूप में चिह्नित करने के लिए किया जाता है। अगर आपके पास फाइलें हैं

mydir/spam/__init__.py
mydir/spam/module.py

और mydirअपने रास्ते पर है, तो आप में कोड आयात कर सकते हैं module.pyके रूप में

import spam.module

या

from spam import module

यदि आप __init__.pyफ़ाइल को हटाते हैं , तो पायथन अब उस निर्देशिका के अंदर सबमॉडल्स की तलाश नहीं करेगा, इसलिए मॉड्यूल आयात करने का प्रयास विफल हो जाएगा।

__init__.pyफ़ाइल आमतौर पर खाली है, लेकिन और अधिक सुविधाजनक नाम, पकड़ सुविधा काम करता है, आदि उपरोक्त उदाहरण को देखते हुए के तहत पैकेज के चयनित भागों निर्यात करने के लिए इस्तेमाल किया जा सकता, init मॉड्यूल की सामग्री के रूप में पहुँचा जा सकता है

import spam

के आधार पर इस


96
अद्यतन: __init__.pyपायथन 2.X के तहत फ़ाइल की आवश्यकता थी और अभी भी पायथन 2.7.12 (मैंने इसे परीक्षण किया है) के तहत आवश्यक है, लेकिन यह अब (कथित रूप से) पायथन 3.3 से आगे की आवश्यकता नहीं है, और पायथन 3.4.3 (I के तहत आवश्यक नहीं है) इसका परीक्षण किया गया)। अधिक जानकारी के लिए stackoverflow.com/questions/37139786 देखें ।
Rob_before_edits

4
इसका उपयोग न करें। यह "नेमस्पेस" पैकेज है, नियमित पैकेज नहीं। नेमस्पेस पैकेज का उपयोग बहुत ही दुर्लभ मामलों के लिए किया जाता है। इसका उपयोग करते समय आपको यह जानने की आवश्यकता नहीं हो सकती है। बस उपयोग करें __init__.py
मिथेन

2
हालांकि अगर आपके पास है setup.pyऔर आप इसका इस्तेमाल find_packages()करते हैं तो __init__.pyहर डायरेक्टरी में इसका होना जरूरी है । देखें stackoverflow.com/a/56277323/7127824
techkuz

483

एक निर्देशिका को पायथन पैकेज के रूप में लेबल करने और परिभाषित करने के अलावा __all__, __init__.pyआप पैकेज स्तर पर किसी भी चर को परिभाषित करने की अनुमति देता है। ऐसा करना अक्सर सुविधाजनक होता है अगर कोई पैकेज ऐसी चीज को परिभाषित करता है जिसे अक्सर आयात किया जाएगा, एपीआई-जैसे फैशन में। यह पैटर्न पाइथोनिक "फ्लैट नेस्टेड से बेहतर है" दर्शन के पालन को बढ़ावा देता है।

एक उदाहरण

यहाँ मेरी परियोजनाओं, जिसमें मैं अक्सर आयात एक में से एक से एक उदाहरण है sessionmakerकहा जाता है Sessionमेरी डेटाबेस के साथ बातचीत करने। मैंने कुछ मॉड्यूल के साथ "डेटाबेस" पैकेज लिखा:

database/
    __init__.py
    schema.py
    insertions.py
    queries.py

मेरा __init__.pyकोड निम्नलिखित है:

import os

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

engine = create_engine(os.environ['DATABASE_URL'])
Session = sessionmaker(bind=engine)

चूंकि मैं Sessionयहां परिभाषित करता हूं , इसलिए मैं नीचे दिए गए सिंटैक्स का उपयोग करके एक नया सत्र शुरू कर सकता हूं। यह कोड "डेटाबेस" पैकेज निर्देशिका के अंदर या बाहर से निष्पादित किया जाएगा।

from database import Session
session = Session()

बेशक, यह एक छोटी सुविधा है - विकल्प Sessionमेरे डेटाबेस पैकेज में "create_session.py" जैसी एक नई फ़ाइल में परिभाषित होगा , और नए सत्रों का उपयोग करना शुरू करेगा:

from database.create_session import Session
session = Session()

आगे की पढाई

यहाँ पर उचित उपयोग के लिए एक बहुत ही रोचक रेडिट धागा __init__.pyहै:

http://www.reddit.com/r/Python/comments/1bbbwk/whats_your_opinion_on_what_to_include_in_init_py/

बहुमत की राय से ऐसा प्रतीत होता है कि __init__.py"स्पष्ट रूप से निहित से बेहतर है" दर्शन का उल्लंघन करने से बचने के लिए फाइलें बहुत पतली होनी चाहिए।


3
engine, sessionmaker, create_engine, और osसब भी से आयात किया जा सकता databaseहै अब ... लगता है कि आपको लगता है कि नाम स्थान की गड़बड़ी कर दिया है।
आर्टऑफवर्फ

9
@ArtOfWarfare, आप __all__ = [...]जो आयात करते हैं, उसे सीमित करने के लिए उपयोग कर सकते हैं import *। लेकिन उस तरफ से, हाँ, आप एक गन्दा शीर्ष-स्तरीय नाम स्थान छोड़ गए हैं।
नाथन गोल्ड

क्या मुझे पता है कि 'DATABASE URL' क्या है? मैंने 'mysql + mysqldb: // root: python @ localhost: 3306 / test' के साथ create_engine को संलग्न करके इसे दोहराने की कोशिश की, लेकिन यह काम नहीं करता है। धन्यवाद।
सनीबोइज़

2
कैसे आप का उपयोग 'सत्र' वर्ग में परिभाषित किया जाएगा init अंदर अंदर पैकेज जैसे quieries.py से?
vldbnc

252

इसके 2 मुख्य कारण हैं __init__.py

  1. सुविधा के लिए: अन्य उपयोगकर्ताओं को आपके पैकेज पदानुक्रम में आपके कार्यों के सटीक स्थान को जानने की आवश्यकता नहीं होगी।

    your_package/
      __init__.py
      file1.py
      file2.py
        ...
      fileN.py
    # in __init__.py
    from file1 import *
    from file2 import *
    ...
    from fileN import *
    # in file1.py
    def add():
        pass

    फिर अन्य लोग कॉल () जोड़ सकते हैं

    from your_package import add

    file1 को जाने बिना, जैसे

    from your_package.file1 import add
  2. यदि आप चाहते हैं कि कुछ प्रारंभिक हो; उदाहरण के लिए, लॉगिंग (जिसे शीर्ष स्तर पर रखा जाना चाहिए):

    import logging.config
    logging.config.dictConfig(Your_logging_config)

6
ओह, आपका जवाब पढ़ने से पहले, मैंने सोचा कि इसके स्थान से स्पष्ट रूप से एक फ़ंक्शन कॉल करना एक अच्छा अभ्यास है।
एरिन

2
@ अगर यह बेहतर होगा कि छोटे बयान (या, इस मामले में, व्यक्तिपरक निष्कर्ष) को हमेशा सच न मानें। से आयात करना __init__.pyकभी-कभी उपयोगी हो सकता है, लेकिन हर समय नहीं।
टोबियास सेट्ट

2
क्या ये कोड आयात समय या रनटाइम पर निष्पादित किए जाते हैं?
user1559897

111

__init__.pyफ़ाइल अजगर इलाज मॉड्यूल के रूप में यह युक्त निर्देशिका बनाता है।

इसके अलावा, यह एक मॉड्यूल में लोड की जाने वाली पहली फाइल है, इसलिए आप इसे कोड को निष्पादित करने के लिए उपयोग कर सकते हैं जिसे आप हर बार मॉड्यूल लोड होने पर चलाना चाहते हैं, या निर्यात किए जाने वाले सबमॉड्यूल निर्दिष्ट करें।


89

पायथन 3.3 के बाद से, __init__.pyअब निर्देशिकाओं को आयात करने योग्य पायथन पैकेजों के रूप में परिभाषित करने की आवश्यकता नहीं है।

PEP 420 की जाँच करें : अंतर्निहित नाम स्थान पैकेज :

पैकेज निर्देशिकाओं के लिए मूल समर्थन, जिन्हें __init__.pyमार्कर फ़ाइलों की आवश्यकता नहीं होती है और स्वचालित रूप से कई पथ खंडों को प्रेरित कर सकते हैं (नामस्थान पैकेजों के लिए विभिन्न तृतीय पक्ष द्वारा प्रेरित, जैसा कि पीईपी 420 में वर्णित है )

यहाँ परीक्षण है:

$ mkdir -p /tmp/test_init
$ touch /tmp/test_init/module.py /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
├── module.py
└── __init__.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

$ rm -f /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
└── module.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

संदर्भ:
https://docs.python.org/3/whatsnew/3.3.html#pep-420-implicit-namespace-packages
https://www.python.org/dev/peps/pep-0420/
Is__init__। अजगर 3 में संकुल की आवश्यकता नहीं है?


3
यह "नेमस्पेस" पैकेज है। नियमित पैकेज के लिए इसका इस्तेमाल न करें।
मिथेन

@methan, क्या आप अपनी टिप्पणी पर विस्तार से बता सकते हैं?
रॉबर्ट लूग ऑक्ट


57

पायथन में पैकेज की परिभाषा बहुत सरल है। जावा की तरह पदानुक्रमित संरचना और निर्देशिका संरचना समान हैं। लेकिन आपके पास __init__.pyएक पैकेज में होना चाहिए। मैं नीचे __init__.pyदिए गए उदाहरण के साथ फाइल की व्याख्या करूंगा :

package_x/
|--  __init__.py
|--    subPackage_a/
|------  __init__.py
|------  module_m1.py
|--    subPackage_b/
|------  __init__.py
|------  module_n1.py
|------  module_n2.py
|------  module_n3.py

__init__.pyखाली हो सकता है, जब तक यह मौजूद है। यह इंगित करता है कि निर्देशिका को एक पैकेज के रूप में माना जाना चाहिए। बेशक, __init__.pyउपयुक्त सामग्री भी सेट कर सकते हैं।

यदि हम मॉड्यूल_ एन 1 में एक फ़ंक्शन जोड़ते हैं:

def function_X():
    print "function_X in module_n1"
    return

चलने के बाद:

>>>from package_x.subPackage_b.module_n1 import function_X
>>>function_X()

function_X in module_n1 

फिर हमने पदानुक्रम पैकेज का अनुसरण किया और मॉड्यूल_ एन 1 फ़ंक्शन को बुलाया। हम __init__.pyइस तरह subPackage_b में उपयोग कर सकते हैं :

__all__ = ['module_n2', 'module_n3']

चलने के बाद:

>>>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

इसलिए * आयात का उपयोग करके, मॉड्यूल पैकेज __init__.pyसामग्री के अधीन है।


पैकेज किए गए पुस्तकालय के माध्यम से समान सेटअप करने के लिए मेरा सेटअप थ्रू कैसे दिखेगा? from package_x.subPackage_b.module_n1 import function_X
20

इसलिए कुंजी यहाँ ले जाना "आयात करना * का उपयोग करना है, मॉड्यूल पैकेज init .py सामग्री के अधीन है"
मिन्नी शि

54

हालांकि पायथन एक __init__.pyफ़ाइल के बिना काम करता है लेकिन आपको अभी भी एक को शामिल करना चाहिए।

यह निर्दिष्ट करता है कि एक पैकेज को एक मॉड्यूल के रूप में माना जाना चाहिए, इसलिए इसे शामिल करें (भले ही यह खाली हो)।

वहाँ भी एक मामला है जहाँ आप वास्तव में एक __init__.pyफ़ाइल का उपयोग कर सकते हैं :

कल्पना करें कि आपके पास निम्न फ़ाइल संरचना थी:

main_methods 
    |- methods.py

और methods.pyइसमें निहित है:

def foo():
    return 'foo'

उपयोग करने के लिए foo()आपको निम्नलिखित में से एक की आवश्यकता होगी:

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()

हो सकता है कि आपको methods.pyअंदर रखने की आवश्यकता हो (या चाहते हैं) main_methods(उदाहरण के लिए रनटाइम / निर्भरता), लेकिन आप केवल आयात करना चाहते हैं main_methods


यदि आपने नाम बदल दिया methods.pyहै __init__.pyतो आप foo()केवल आयात करके उपयोग कर सकते हैं main_methods:

import main_methods
print(main_methods.foo()) # Prints 'foo'

यह काम करता है क्योंकि __init__.pyपैकेज के हिस्से के रूप में माना जाता है।


कुछ पायथन पैकेज वास्तव में ऐसा करते हैं। एक उदाहरण JSON के साथ है , जहां रनिंग import jsonवास्तव __init__.pyमें jsonपैकेज से आयात हो रहा है ( पैकेज फ़ाइल संरचना यहां देखें ):

सोर्स कोड: Lib/json/__init__.py


39

__init__.py निर्देशिका का इलाज यह एक लोड करने योग्य मॉड्यूल के रूप में होगा।

जो लोग कोड पढ़ना पसंद करते हैं, उनके लिए मैंने टू-बिट अल्केमिस्ट की टिप्पणी यहां दी है।

$ find /tmp/mydir/
/tmp/mydir/
/tmp/mydir//spam
/tmp/mydir//spam/__init__.py
/tmp/mydir//spam/module.py
$ cd ~
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
>>> module.myfun(3)
9
>>> exit()
$ 
$ rm /tmp/mydir/spam/__init__.py*
$ 
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named spam
>>> 

30

यह अन्य अजगर फ़ाइलों को आयात करने की सुविधा देता है। जब आपने इस फाइल को एक निर्देशिका (सामान कहो) में रखा, जिसमें अन्य py फाइलें थीं, तब आप कुछ चीजें आयात कर सकते हैं।

root\
    stuff\
         other.py

    morestuff\
         another.py

__init__.pyनिर्देशिका सामान के अंदर इसके बिना , आप अन्य थिंक को आयात नहीं कर सकते, क्योंकि पायथन को नहीं पता है कि सामान के लिए स्रोत कोड कहां है और इसे पैकेज के रूप में पहचानने में असमर्थ है।


2
मेरी परियोजना (python 3.4) में मेरी संरचना समान है, लेकिन मैं अन्य एरेन्डो को देखने के लिए दूसरी थिंकपैड बनाने में सक्षम नहीं हूं। मुझे आयात कैसे करना चाहिए? root.stuff आयात से अन्य? यह VSCode डिबग मोड में काम करता है लेकिन कमांड लाइन में नहीं। कोई विचार?
कृतिगोर्फ

10

एक __init__.pyफ़ाइल आयात को आसान बनाती है। जब कोई __init__.pyपैकेज के भीतर मौजूद होता है, तो फ़ंक्शन a()को फ़ाइल से आयात किया जा सकता है b.pyजैसे:

from b import a

इसके बिना, हालांकि, आप सीधे आयात नहीं कर सकते। आपको सिस्टम पथ में संशोधन करना होगा:

import sys
sys.path.insert(0, 'path/to/b.py')

from b import a

आपका क्या मतलब है " फ़ंक्शन (ए) फ़ाइल b.py [snippet] से आयात किया जा सकता है, इसके बिना, हालांकि, आप सीधे आयात नहीं कर सकते। " मैं __init__.py के बिना फ़ाइल b.py से फ़ंक्शन (a) आयात कर सकता हूं।
एड्रॉक्सॉक्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.