__Init__.py पर कोड जोड़ना


85

मैं देख रहा हूँ कि कैसे django में मॉडल सिस्टम काम करता है और मैंने कुछ ऐसा देखा है जो मुझे समझ में नहीं आता है।

मुझे पता है कि आप __init__.pyयह निर्दिष्ट करने के लिए एक खाली फ़ाइल बनाते हैं कि वर्तमान निर्देशिका एक पैकेज है। और यह कि आप कुछ चर सेट कर सकते हैं __init__.pyताकि आयात * ठीक से काम करे।

लेकिन django से ... आयात ... बयानों का एक समूह जोड़ता है और कक्षाओं में वर्गों का एक गुच्छा परिभाषित करता है __init__.py। क्यों? क्या यह सिर्फ चीजों को गड़बड़ नहीं बनाता है? क्या कोई कारण है जिसमें इस कोड की आवश्यकता है __init__.py?


13
यह वास्तव में Django के बारे में नहीं है? हां, आपने इसे पहली बार Django में देखा था, लेकिन यह एक शुद्ध पायथन की तरह लगता है - शायद Django टैग वास्तव में उपयुक्त नहीं है।
एस.लॉट

मुझे __init__.pydjango 1.8 में कोई भी आयात विवरण नहीं दिख रहा है । क्या यह पुराने संस्करण के लिए था? यदि ऐसा है तो कौन सा संस्करण?
गोबी दासू

जवाबों:


72

__init__.pyजब आप पैकेज (निर्देशिका) को आयात करते हैं तो सभी आयात उपलब्ध होते हैं।

उदाहरण:

./dir/__init__.py:

import something

./test.py:

import dir
# can now use dir.something

EDIT: उल्लेख करना भूल गया, कोड __init__.pyपहली बार जब आप उस निर्देशिका से किसी भी मॉड्यूल को आयात करते हैं। तो यह आम तौर पर किसी भी पैकेज-स्तरीय आरंभीकरण कोड को रखने के लिए एक अच्छी जगह है।

EDIT2: dgrant ने मेरे उदाहरण में संभावित भ्रम की ओर इशारा किया। में __init__.py import somethingकिसी भी मॉड्यूल, पैकेज से आवश्यक नहीं आयात कर सकते हैं। उदाहरण के लिए, हम इसे बदल सकते हैं import datetime, फिर हमारे शीर्ष स्तर test.pyमें ये दोनों स्निपेट काम करेंगे:

import dir
print dir.datetime.datetime.now()

तथा

import dir.some_module_in_dir
print dir.datetime.datetime.now()

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


ठीक है शुक्रिया। लेकिन मुझे अभी भी यकीन नहीं है कि कक्षाओं को जोड़ना एक अच्छा विचार होगा क्योंकि __init__.py मैं वास्तव में इन कक्षाओं को आरंभीकरण कोड नहीं मानता हूं (लेकिन शायद मैं इसके बारे में गलत हूं)।
एरिक

ये शायद वे कक्षाएं हैं जो हर बार आपके पैकेज के साथ काम करने के लिए उपयोगी होती हैं। लेकिन मैं अटकलें नहीं
लगाना

13
यह ऐतिहासिक कारणों से भी हो सकता है। जब आप मॉड्यूल को पैकेज में परिवर्तित कर रहे हैं, तो मॉड्यूल / मॉड्यूल से ___ init__.py सभी मौजूदा कोड पहले की तरह उपयोग कर सकते हैं, लेकिन अब मॉड्यूल में सबमॉड्यूल हो सकते हैं।
कसज़

1
मॉड्यूल मूल __init__.pyरूप से माता-पिता को निष्पादित करते हैं । अंदर मॉड्यूल आयात करके __init__.py, आप चक्रीय आयात बना रहे हैं। इस __init__.pyतरह के एक आयात से पहले पूरी तरह से निष्पादित नहीं किया जाएगा। __init__.pyखाली रखना सुरक्षित है ।
इवो ​​डनिहेलका

यह टिप्पणी करना महत्वपूर्ण है कि यह __init__.pyफाइलों के लिए कुछ खास नहीं है । आप एक फ़ाइल था dir/other.pyजो कुछ किया था की तरह from datetime import datetimeआप भी फोन करने में सक्षम होगा dir.other.datetime.now()भी या from dir.other import datetime
सला

37

यह वास्तव में सिर्फ व्यक्तिगत पसंद है, और अपने अजगर मॉड्यूल के लेआउट के साथ करना है।

मान लीजिए कि आपके पास एक मॉड्यूल है जिसे कहा जाता है erikutils। दो तरीके है कि यह एक मॉड्यूल हो सकता है, या तो आप एक फ़ाइल कहा जाता है erikutils.py अपने पर sys.pathया आप एक निर्देशिका कहा जाता है erikutils अपने पर sys.pathएक खाली साथ __init__.pyइसके अंदर फ़ाइल। तो मान लीजिए कि आप बुलाया मॉड्यूल का एक समूह है चलो fileutils, procutils, parseutilsऔर आप उन के तहत उप मॉड्यूल होना चाहता हूँ erikutils। तो अगर आप कुछ .py बुलाया फ़ाइलें बनाने fileutils.py , procutils.py , और parseutils.py :

erikutils
  __init__.py
  fileutils.py
  procutils.py
  parseutils.py

हो सकता है कि आप कुछ कार्यों कि बस में संबंधित नहीं है fileutils, procutilsया parseutilsमॉड्यूल। और मान लें कि आपको नया मॉड्यूल बनाने का मन नहीं है miscutils। और, आप इस तरह से फ़ंक्शन को कॉल करने में सक्षम होना चाहते हैं:

erikutils.foo()
erikutils.bar()

करने के बजाय

erikutils.miscutils.foo()
erikutils.miscutils.bar()

इसलिए क्योंकि erikutilsमॉड्यूल एक निर्देशिका है, एक फ़ाइल नहीं है, हमें यह परिभाषित करना होगा कि यह __init__.pyफ़ाइल के अंदर कार्य करता है।

Django में, सबसे अच्छा उदाहरण मैं सोच सकता हूं django.db.models.fields। सभी django * फ़ील्ड कक्षाओं को django / db / मॉडल / फ़ील्ड निर्देशिका __init__.pyमें फ़ाइल में परिभाषित किया गया है । मुझे लगता है कि वे ऐसा किया क्योंकि वे एक काल्पनिक में रटना सब कुछ नहीं करना चाहता था Django / db / मॉडल / fields.py मॉडल है, इसलिए वे इसे कुछ submodules में बाहर विभाजित ( related.py , files.py , उदाहरण के लिए) और उन्होंने फील्ड मॉड्यूल में ही बनी * फील्ड परिभाषाओं को खुद से चिपका दिया (इसलिए, )।__init__.py


1
dgrant, मेरा मतलब है कि somethingबाहरी मॉड्यूल हो सकता है, dir.something काम को पूरा करेगा। टिप्पणी के लिए धन्यवाद, मैं इसे और अधिक स्पष्ट करने के लिए अपनी पोस्ट संपादित करूंगा।
अलेक्जेंडर कोजेविकोव

29

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

ध्यान दें कि आप delकमांड का उपयोग कर सकते हैं , इसलिए एक विशिष्ट __init__.pyइस तरह दिख सकता है:

from somemodule import some_function1, some_function2, SomeObject

del somemodule

अब यदि आप विभाजित करने का निर्णय लेते हैं somemoduleतो नया __init__.pyहो सकता है:

from somemodule1 import some_function1, some_function2
from somemodule2 import SomeObject

del somemodule1
del somemodule2

बाहर से पैकेज अभी भी पहले की तरह ही दिखता है।


1
@Arlen: मुद्दा यह है कि यह सार्वजनिक API का हिस्सा नहीं है। यदि आप एक मॉड्यूल का नाम बदलते हैं, तो आप सुनिश्चित हो सकते हैं कि कोई निर्भर कोड नहीं टूटता है। इसके अतिरिक्त यह सुनिश्चित करता है कि एपीआई तत्व केवल एक बार दिखाई देते हैं, उदाहरण के लिए, जब आत्मनिरीक्षण का उपयोग स्वचालित रूप से एपीआई प्रलेखन बनाने के लिए किया जाता है।
निको

5
@Arlen: किसी मॉड्यूल को हटाना import <pack>.somemodule1सीधे किसी को रोकता है । आप केवल <pack>परिभाषित वस्तुओं से आयात कर सकते हैं या इसके __init__.py, और गैर-हटाए गए सबमॉड्यूल में आयात कर सकते हैं ।
MestreLion
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.