क्या Python 3.3+ में संकुल के लिए __init__.py की आवश्यकता नहीं है


193

मैं पायथन 3.5.1 का उपयोग कर रहा हूं। मैंने दस्तावेज़ और पैकेज अनुभाग यहाँ पढ़ा: https://docs.python.org/3/tutorial/modules.html#packages

अब, मेरे पास निम्नलिखित संरचना है:

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

module.py:

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

अब, जबकि /home/wujek/Playground:

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

इसी तरह, अब घर में, का सुपरफॉल्डर Playground:

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

वास्तव में, मैं सभी प्रकार के सामान कर सकता हूं:

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

यह काम क्यों करता है? मैं हालांकि वहाँ होने की जरूरत __init__.pyफ़ाइलें (खाली लोगों काम करेगा) दोनों में aऔर bके लिए module.pyआयात योग्य होने के लिए जब करने के लिए पायथन पथ अंक Playgroundफ़ोल्डर?

ऐसा लगता है कि पायथन 2.7 से बदल गया है:

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

साथ __init__.pyदोनों में ~/Playground/aऔर ~/Playground/a/bयह ठीक काम करता है।

जवाबों:


191

Python 3.3+ में Implicit Namespace पैकेज हैं जो इसे बिना __init__.pyफाइल के पैकेज बनाने की अनुमति देते हैं ।

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

__init__.pyफ़ाइलों के साथ पुराना तरीका अभी भी पायथन 2 के रूप में काम करता है।


10
मैं दस्तावेज़ पढ़ूंगा, लेकिन यह थोड़ा लंबा है। क्या यह जल्दी से संक्षेप में संभव है? क्या आप मुझे बता सकते हैं: क्या यह अभी भी init .py का समर्थन करता है , या पूरी तरह से उन्हें अनदेखा करता है? यदि यह उनका समर्थन करता है, तो कार्यक्षमता में क्या अंतर है और यह द्वंद्व क्यों है?
वुजेक

3
तो ट्यूटोरियल शायद अद्यतन किया जाना चाहिए। क्या इसके लिए एक दस्तावेज बग खोला गया है?
मिशेल

4
मैं अभी भी परेशान हूं कि यह Zen Of Python लाइन 2 को Explicit is better than implicit.
धता बताता है

5
@JayRizzo लेकिन: "हालांकि व्यावहारिकता शुद्धता को हरा देती है।"
माइक मुलर

18
@JayRizzo IMO यह और भी स्पष्ट है। कभी-कभी यह init stuff करने के लिए होता है __init__.py, कभी-कभी नहीं। पायथन 3 में जब मुझे इन सामानों की आवश्यकता होती है तो मैं __init__.pyविशिष्ट कोड के साथ एक नया निर्माण करता हूं, अन्यथा मैं नहीं। यह जानने के लिए आसान है, नेत्रहीन, किन पैकेजों में कस्टम इनिट है। अजगर 2 के बजाय मुझे हमेशा एक __init__.py(अक्सर खाली) रखना पड़ता है, जिससे उनमें से एक बड़ी संख्या बनती है और अंत में याद रखने में मुश्किल होती है कि आपने अपना इनट कोड कहां रखा है। यह भी फिट होना चाहिए "एक होना चाहिए - और अधिमानतः इसे करने के लिए केवल एक - स्पष्ट तरीका।"
पाओलो

146

जरूरी

@ माइक का जवाब सही है लेकिन बहुत ही गलत है। यह सच है कि पायथन 3.3+ इम्प्लिमेंट नेमस्पेस पैकेज का समर्थन करता है जो इसे एक __init__.pyफ़ाइल के बिना पैकेज बनाने की अनुमति देता है ।

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

निर्देशिका संरचना उदाहरण:

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

उदाहरण

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

उदाहरण 1 :

from parent_package import child_package  # prints "from parent"

उदाहरण 2 :

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

2
मान लीजिए कि मेरे पास run_script.pyएक ही तरह का डायर है, parent_packageतो क्या मैं from parent_package.child_package import child1बिना आयात के बस आयात कर सकता हूं __init__.py?
मर्ग्लोम

क्या इसका उद्देश्य यह है कि आप child_package.some_function लिख सकते हैं, भले ही some_function को चाइल्डएक्सएफ़डी में परिभाषित किया गया हो? दूसरे शब्दों में, यह उपयोगकर्ता को बाल_पैकेज की विभिन्न फाइलों के बारे में जानने से बचता है? ?
जॉनबर्स

हाँ, मैं तुम क्यों बनाना होगा नहीं मिलता है child1.py, child2.pyसिर्फ अपने कोड एक साथ में डाल के बजाय __init__.py सीधे।
बिंकी

में आयात बयान नहीं करना चाहिए __init__हो रिश्तेदार आयात यानी from . import child1? पूर्ण आयात मुझे देता है ModuleNotFoundError(अजगर 3.6 में)
Halbeard

5
मेरे अनुभव में, यहां तक ​​कि 3.3+ के साथ भी, एक खाली __init__.pyको अभी भी कभी-कभी ज़रूरत होती है, जैसे कि जब आप एक सबफ़ोल्डर को पैकेज के रूप में संदर्भित करना चाहते हैं। उदाहरण के लिए, अगर मैं python -m test.fooइसे चलाता हूं तो तब तक काम नहीं करता, जब तक कि मैं __init__.pyटेस्ट फ़ोल्डर के नीचे खाली नहीं हो जाता। और मैं यहाँ 3.6.6 संस्करण की बात कर रहा हूँ!
प्रहलाद यारी

6

यदि आपके पास setup.pyअपनी परियोजना है और आप find_packages()इसके भीतर उपयोग करते हैं, तो __init__.pyस्वचालित रूप से पाए जाने वाले पैकेजों के लिए प्रत्येक निर्देशिका में एक फ़ाइल होना आवश्यक है ।

पैकेज केवल तभी पहचाने जाते हैं यदि वे एक __init__.pyफ़ाइल शामिल करते हैं

UPD : यदि आप बिना किसी अंतर्निहित नामस्थान पैकेज का उपयोग करना चाहते __init__.pyहैं, तो आपको find_namespace_packages()इसके बजाय उपयोग करना होगा

डॉक्स


1

मैं कहूंगा कि किसी को __init__.pyकेवल एक ही नाम छोड़ना चाहिए यदि कोई निहित नाम स्थान पैकेज चाहता है । यदि आपको नहीं पता कि इसका क्या मतलब है, तो आप शायद यह नहीं चाहते हैं और इसलिए आपको __init__.pyपायथन 3 में भी इसका उपयोग जारी रखना चाहिए ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.