क्या आयात विवरण हमेशा एक मॉड्यूल के शीर्ष पर होना चाहिए?


403

पीईपी 08 राज्यों:

आयात हमेशा फ़ाइल के शीर्ष पर, किसी भी मॉड्यूल टिप्पणियों और docstrings के बाद, और मॉड्यूल ग्लोबल्स और स्थिरांक से पहले किया जाता है।

हालाँकि, यदि मैं जिस क्लास / मेथड / फंक्शन को इंपोर्ट कर रहा हूं, वह केवल रेयर केस में ही इस्तेमाल किया जाता है, तो निश्चित तौर पर जरूरत पड़ने पर इम्पोर्ट करना ज्यादा कारगर होता है?

यह नहीं है:

class SomeClass(object):

    def not_often_called(self)
        from datetime import datetime
        self.datetime = datetime.now()

इससे अधिक कुशल?

from datetime import datetime

class SomeClass(object):

    def not_often_called(self)
        self.datetime = datetime.now()

जवाबों:


283

मॉड्यूल आयात काफी तेज है, लेकिन तत्काल नहीं। इस का मतलब है कि:

  • मॉड्यूल के शीर्ष पर आयात करना ठीक है, क्योंकि यह एक तुच्छ लागत है जो केवल एक बार भुगतान की जाती है।
  • किसी फ़ंक्शन के भीतर आयात को डालने से उस फ़ंक्शन को कॉल करने में अधिक समय लगेगा।

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


आलसी आयात करने के लिए मैंने सबसे अच्छे कारण देखे हैं:

  • वैकल्पिक पुस्तकालय समर्थन। यदि आपके कोड में कई पथ हैं जो अलग-अलग पुस्तकालयों का उपयोग करते हैं, तो वैकल्पिक लाइब्रेरी स्थापित नहीं होने पर टूट न जाएं।
  • में __init__.pyएक प्लगइन, आयात किया जा सकता है जो, लेकिन वास्तव में इस्तेमाल नहीं किया की। उदाहरण बाज़ार के प्लग-इन हैं, जो bzrlibआलसी-लोडिंग ढांचे का उपयोग करते हैं।

17
जॉन, यह एक पूरी तरह से सैद्धांतिक सवाल था इसलिए मेरे पास प्रोफ़ाइल का कोई कोड नहीं था। अतीत में मैंने हमेशा PEP का अनुसरण किया है, लेकिन मैंने आज कुछ कोड लिखे जिससे मुझे आश्चर्य हुआ कि क्या यह सही बात थी। आपकी सहायता के लिए धन्यवाद।
एडम जे। फोर्स्टर

43
> किसी फंक्शन के भीतर इंपोर्ट करने से उस फंक्शन में कॉल आने में देर लगेगी। वास्तव में, मुझे लगता है कि यह लागत केवल एक बार के लिए भुगतान की जाती है। मैंने पढ़ा है कि पायथन एक आयातित मॉड्यूल को कैश करता है ताकि इसे फिर से आयात करने के लिए न्यूनतम लागत हो।
मोल्टेनफॉर्म

24
@halfhourhacks Python मॉड्यूल को पुन: आयात नहीं करेगा, लेकिन अभी भी यह देखने के लिए कुछ निर्देश देने हैं कि क्या मॉड्यूल मौजूद है / sys.modules / आदि में है
जॉन मिलिकिन

24
-1। किसी फ़ंक्शन में आयात करना आवश्यक रूप से इसे अधिक समय लेने का कारण नहीं बनाता है। कृपया किसी अन्य प्रश्न पर मेरा उत्तर देखें ।
अप्रैल को

4
एक उपयोग का मामला परिपत्र आयात से बच रहा है (आमतौर पर समझदार नहीं है, लेकिन कभी-कभी यह उपयुक्त है)। कभी-कभी मॉड्यूल एम 1 में क्लास ए, मॉड्यूल एम 2 में क्लास बी पर एक विधि को कॉल करता है जो क्लास ए का एक और उदाहरण का निर्माण करता है। यदि क्लास बी में विधि जो क्लास ए की एक आवृत्ति का निर्माण करती है, तो केवल एक फ़ंक्शन का निर्माण करने वाले फ़ंक्शन को निष्पादित करने पर आयात रन होता है, परिपत्र आयात से बचा जाता है।
सैम स्वेनबॉर्गोक्रिस्टिंसेंसन

80

किसी फंक्शन के अंदर इंपोर्ट स्टेटमेंट डालने से सर्कुलर डिपेंडेंसी को रोका जा सकता है। उदाहरण के लिए, यदि आपके पास 2 मॉड्यूल हैं, तो X.py और Y.py, और उन्हें दोनों को एक दूसरे को आयात करने की आवश्यकता है, जब आप एक अनंत लूप पैदा करने वाले मॉड्यूल में से किसी एक को आयात करते हैं तो यह एक परिपत्र निर्भरता का कारण होगा। यदि आप किसी एक मॉड्यूल में आयात स्टेटमेंट को स्थानांतरित करते हैं तो यह फ़ंक्शन को कॉल करने तक अन्य मॉड्यूल को आयात करने की कोशिश नहीं करेगा, और वह मॉड्यूल पहले से ही आयात किया जाएगा, इसलिए कोई अनंत लूप नहीं। अधिक के लिए यहां पढ़ें - effbot.org/zone/import-confusion.htm


3
हाँ, लेकिन एक निर्भरता नरक में मिल सकता है।
ईजीनिन

8
यदि दो मॉड्यूल को एक दूसरे को आयात करने की आवश्यकता होती है, तो कोड के साथ कुछ गंभीर रूप से गलत है।
अन्ना

ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग अक्सर मुझे परिपत्र निर्भरता की ओर ले जाती है। एक महत्वपूर्ण वस्तु वर्ग को कई मॉड्यूल में आयात किया जा सकता है। इस ऑब्जेक्ट को अपने स्वयं के कार्यों को करने के लिए, इसे उन मॉड्यूलों में से एक या अधिक तक पहुंचने की आवश्यकता हो सकती है। इससे बचने के तरीके हैं, जैसे कि फ़ंक्शन आर्ग के माध्यम से ऑब्जेक्ट को डेटा भेजना, जिससे वह दूसरे मॉड्यूल तक पहुंच सके। लेकिन ऐसे समय होते हैं जब ऐसा करने से ओओपी के प्रति बहुत ही सहज ज्ञान युक्त लगता है (बाहरी दुनिया को यह जानने की आवश्यकता नहीं है कि उस कार्य को कैसे पूरा किया जाए)।
रॉबर्ट

4
जब X को Y की आवश्यकता होती है और Y को X की आवश्यकता होती है, वे या तो एक ही विचार के दो भाग होते हैं (यानी एक साथ परिभाषित किए जाने चाहिए) या एक लापता अमूर्त है।
GLRoman

59

मैंने सभी आयातों को उन कार्यों में लगाने का अभ्यास अपनाया है जो मॉड्यूल के शीर्ष पर होने के बजाय उनका उपयोग करते हैं।

मुझे जो लाभ मिल रहा है, वह मज़बूती से और अधिक मज़बूती देने की क्षमता है। जब मैं एक फ़ंक्शन को एक मॉड्यूल से दूसरे में ले जाता हूं, तो मुझे पता है कि फ़ंक्शन अपने सभी परीक्षण की विरासत के साथ काम करना जारी रखेगा। यदि मॉड्यूल के शीर्ष पर मेरा आयात होता है, जब मैं एक फ़ंक्शन को स्थानांतरित करता हूं, तो मुझे पता चलता है कि मैं नए मॉड्यूल के आयात को पूर्ण और न्यूनतम प्राप्त करने में बहुत समय खर्च करता हूं। एक refactoring IDE इसे अप्रासंगिक बना सकती है।

अन्यत्र बताए अनुसार गति का दंड है। मैंने इसे अपने आवेदन में मापा है और इसे अपने उद्देश्यों के लिए महत्वहीन पाया है।

खोज का सहारा लिए बिना सभी मॉड्यूल पर निर्भरता को देखने में सक्षम होना अच्छा है (उदाहरण के लिए grep)। हालाँकि, मैं मॉड्यूल निर्भरता के बारे में परवाह करने का कारण आम तौर पर क्योंकि मैं स्थापित कर रहा हूँ, refactoring, या एक पूरी प्रणाली चलती है जिसमें कई फाइलें शामिल हैं, न कि केवल एक मॉड्यूल। उस स्थिति में, मैं यह सुनिश्चित करने के लिए एक वैश्विक खोज का प्रदर्शन करने जा रहा हूं कि मेरे पास सिस्टम-स्तरीय निर्भरताएं हैं। इसलिए मुझे व्यवहार में एक प्रणाली की मेरी समझ में सहायता करने के लिए वैश्विक आयात नहीं मिला है।

मैं आमतौर पर चेक के sysअंदर आयात करता हूं if __name__=='__main__'और फिर sys.argv[1:]एक main()फ़ंक्शन के लिए तर्क (जैसे ) पास करता हूं । यह मुझे mainऐसे संदर्भ में उपयोग करने की अनुमति देता है जहां sysआयात नहीं किया गया है।


4
कई आईडीई आपके लिए आपकी फ़ाइल में आवश्यक मॉड्यूल को अनुकूलित और ऑटो-आयात करके कोड को फिर से भरना आसान बनाते हैं। बहुमत के मामलों में PyCharm और Eclipse ने मेरे लिए सही निर्णय लिए हैं। मैं शर्त लगा सकता हूँ कि emacs या vim में समान व्यवहार प्राप्त करने का एक तरीका है।
ब्रेंट.पेने

3
वैश्विक नाम स्थान में एक बयान के अंदर एक आयात अभी भी एक वैश्विक आयात है। यह तर्क मुद्रित करेगा (पायथन 3 का उपयोग करके): def main(): print(sys.argv); if True: import sys; main();आपको if __name__=='__main__'एक नया नामस्थान बनाने के लिए फ़ंक्शन में लपेटना होगा ।
दरसिनों

4
यह मुझे वैश्विक दायरे के बजाय कार्यों के भीतर आयात करने के लिए एक उत्कृष्ट कारण के रूप में प्रभावित करता है। मुझे काफी आश्चर्य है कि किसी और ने भी इसी कारण से इसका उल्लेख नहीं किया है। क्या प्रदर्शन और वाचालता के अलावा कोई महत्वपूर्ण गिरावट है?
algal

@ लेगल नकारात्मक पक्ष यह है कि कई अजगर लोग इससे नफरत करते हैं क्योंकि आप पेप कोडेक्स का उल्लंघन करते हैं। आपको अपने टीम के सदस्यों को समझाना होगा। प्रदर्शन जुर्माना न्यूनतम है। कभी-कभी यह और भी तेज होता है, देखें stackoverflow.com/a/4789963/362951
mit

मैंने पाया कि जहाँ मैं उनका उपयोग करता हूँ, वहाँ आयातों को बंद करने के लिए इसे फिर से तैयार करना बेहद उपयोगी है। इतने समय में ऊपर और पीछे स्क्रॉल करना आवश्यक नहीं है। मैं IDEs जैसे pycharm या विंग ide का उपयोग करता हूं और उनके रीफैक्टरिंग का भी उपयोग करता हूं, लेकिन मैं हमेशा उन पर भरोसा नहीं करना चाहता। इस वैकल्पिक आयात शैली के साथ किसी अन्य मॉड्यूल के लिए फ़ंक्शन करना बहुत आसान हो जाता है, परिणामस्वरूप मैं और अधिक रिफ्लेक्टर करता हूं।
mit

39

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

सबसे पहले, आपके पास प्रपत्र की एक इकाई परीक्षण के साथ एक मॉड्यूल हो सकता है:

if __name__ == '__main__':
    import foo
    aa = foo.xyz()         # initiate something for the test

दूसरे, आपको रनटाइम पर कुछ अलग मॉड्यूल को सशर्त रूप से आयात करने की आवश्यकता हो सकती है।

if [condition]:
    import foo as plugin_api
else:
    import bar as plugin_api
xx = plugin_api.Plugin()
[...]

संभवतः अन्य परिस्थितियां हैं जहां आप कोड में अन्य भागों में आयात कर सकते हैं।


14

पहला संस्करण वास्तव में दूसरे की तुलना में अधिक कुशल है जब फ़ंक्शन को शून्य या एक बार कहा जाता है। दूसरे और बाद के आक्रमणों के साथ, हालांकि, "हर कॉल आयात करें" दृष्टिकोण वास्तव में कम कुशल है। एक आलसी-लोडिंग तकनीक के लिए इस लिंक को देखें जो "आलसी आयात" करके दोनों दृष्टिकोणों में से सर्वश्रेष्ठ को जोड़ती है।

लेकिन दक्षता के अलावा अन्य कारण हैं कि आप एक से दूसरे को क्यों पसंद कर सकते हैं। एक दृष्टिकोण इस मॉड्यूल के लिए निर्भरता के रूप में कोड को पढ़ने वाले किसी व्यक्ति के लिए बहुत अधिक स्पष्ट करता है। उनके पास बहुत भिन्न विफलता विशेषताएं भी हैं - पहला लोड समय पर विफल होगा यदि कोई "डेटाइम" मॉड्यूल नहीं है, जबकि दूसरा तब तक विफल नहीं होगा जब तक कि विधि को नहीं बुलाया जाता है।

जोड़ा गया नोट: आयरनपाइथन में, आयात CPython की तुलना में थोड़ा अधिक महंगा हो सकता है क्योंकि कोड मूल रूप से संकलित किया जा रहा है क्योंकि यह आयात किया जा रहा है।


1
यह सच नहीं है कि पहले वाला बेहतर प्रदर्शन करता है: wiki.python.org/moin/PythonSpeed/…
जेसन बेकर

यह बेहतर प्रदर्शन करता है अगर विधि को कभी नहीं बुलाया जाता है क्योंकि आयात कभी नहीं होता है।
कर्ट हेगनलोचर

यह सच है, लेकिन अगर यह विधि एक से अधिक बार कॉल की जाती है, तो यह और भी खराब होता है। और मॉड्यूल को आयात नहीं करने से आपको जो लाभ होगा, वह ज्यादातर मामलों में नगण्य है। अपवाद होगा यदि मॉड्यूल बहुत बड़ा है या इस प्रकार के बहुत सारे कार्य हैं।
जेसन बेकर

आयरनपाइथन दुनिया में, शुरुआती आयात सीपीथॉन की तुलना में बहुत अधिक महंगे हैं;)। आपके लिंक में "आलसी आयात" उदाहरण संभवतः सबसे अच्छा समग्र सामान्य समाधान है।
कर्ट हेगनलोचर

मुझे आशा है कि आपको कोई आपत्ति नहीं होगी, लेकिन मैंने इसे अपनी पोस्ट में संपादित किया। यह जानने के लिए उपयोगी जानकारी है।
जेसन बेकर

9

कर्ट एक अच्छा बिंदु बनाता है: दूसरा संस्करण स्पष्ट है और बाद में और अनपेक्षित रूप से लोड समय पर विफल हो जाएगा।

आम तौर पर मैं लोडिंग मॉड्यूल की दक्षता के बारे में चिंता नहीं करता, क्योंकि यह (ए) बहुत तेज है, और (बी) ज्यादातर स्टार्टअप पर ही होता है।

यदि आपको अप्रत्याशित समय पर हैवीवेट मॉड्यूल लोड करना है, तो यह संभवतः __import__फ़ंक्शन के साथ उन्हें गतिशील रूप से लोड करने के लिए अधिक समझ में आता है , और अपवादों को पकड़ना सुनिश्चित करेंImportError , और उन्हें उचित तरीके से संभालें।


8

मैं बहुत आगे मॉड्यूल लोड करने की दक्षता के बारे में चिंता नहीं करेगा। मॉड्यूल द्वारा ली गई मेमोरी बहुत बड़ी नहीं होगी (यह मानते हुए कि यह पर्याप्त रूप से मॉड्यूलर है) और स्टार्टअप की लागत नगण्य होगी।

ज्यादातर मामलों में आप स्रोत फ़ाइल के शीर्ष पर मॉड्यूल लोड करना चाहते हैं। आपके कोड को पढ़ने वाले किसी व्यक्ति के लिए, यह बताना बहुत आसान हो जाता है कि कौन सा फ़ंक्शन या ऑब्जेक्ट किस मॉड्यूल से आया है।

एक मॉड्यूल को कोड में कहीं और आयात करने का एक अच्छा कारण यह है कि अगर यह डिबगिंग स्टेटमेंट में उपयोग किया जाता है।

उदाहरण के लिए:

do_something_with_x(x)

मैं इसके साथ डीबग कर सकता था:

from pprint import pprint
pprint(x)
do_something_with_x(x)

बेशक, कोड में कहीं और मॉड्यूल आयात करने का दूसरा कारण यह है कि क्या आपको उन्हें गतिशील रूप से आयात करने की आवश्यकता है। ऐसा इसलिए है क्योंकि आपके पास कोई विकल्प नहीं है।

मैं बहुत आगे मॉड्यूल लोड करने की दक्षता के बारे में चिंता नहीं करेगा। मॉड्यूल द्वारा ली गई मेमोरी बहुत बड़ी नहीं होगी (यह मानते हुए कि यह पर्याप्त रूप से मॉड्यूलर है) और स्टार्टअप की लागत नगण्य होगी।


हम प्रति मॉड्यूल (मेरी मशीन पर) स्टार्टअप लागत के दसियों मिलीसेकंड के बारे में बात कर रहे हैं। यह हमेशा नगण्य नहीं है, उदाहरण के लिए, यदि यह किसी उपयोगकर्ता के क्लिक करने के लिए वेब एप्लिकेशन की जवाबदेही को प्रभावित करता है।
इवगेनी सर्गेव

6

यह एक व्यापार है, जिसे केवल प्रोग्रामर ही तय कर सकता है।

केस 1 जरूरत पड़ने तक डेटाइम मॉड्यूल (और जो भी आरंभीकरण की आवश्यकता होती है) को आयात नहीं करके कुछ मेमोरी और स्टार्टअप समय बचाता है। ध्यान दें कि 'केवल कहे जाने पर' आयात करने का मतलब यह भी है कि 'हर बार जब बुलाया जाए', इसलिए पहले एक के बाद प्रत्येक कॉल अभी भी आयात करने के अतिरिक्त ओवरहेड को कर रहा है।

केस 2 सेव कुछ निष्पादन समय और विलंबता datetime पहले से इतना है कि not_often_called (आयात करके) और अधिक तेजी से वापस आ जाएगी जब यह है हर कॉल पर एक आयात की भूमि के ऊपर उठाने नहीं द्वारा कहा जाता है, और यह भी।

दक्षता के अलावा, मॉड्यूल निर्भरता को सामने देखना आसान है अगर आयात बयान हैं ... सामने। कोड में उन्हें छुपाने से यह आसानी से पता लगाना मुश्किल हो सकता है कि मॉड्यूल कुछ पर निर्भर करता है।

व्यक्तिगत रूप से मैं आमतौर पर पीईपी का पालन करता हूं, जैसे कि यूनिट परीक्षण और ऐसी चीजें जो मैं हमेशा लोड नहीं करना चाहता, क्योंकि मुझे पता है कि वे परीक्षण कोड को छोड़कर उपयोग नहीं करने जा रहे हैं।


2
-1। आयात करने का मुख्य ओवरहेड पहली बार होता है। मॉड्यूल sys.modulesको देखने की लागत को केवल एक वैश्विक नाम के बजाय एक स्थानीय नाम देखने के लिए बचत द्वारा आसानी से ऑफसेट किया जा सकता है।
एरोनस्टरलिंग

6

यहां एक उदाहरण है जहां सभी आयात बहुत ऊपर हैं (यह एकमात्र समय है जब मुझे ऐसा करने की आवश्यकता है)। मैं Un * x और Windows दोनों पर एक उपप्रकार को समाप्त करने में सक्षम होना चाहता हूं।

import os
# ...
try:
    kill = os.kill  # will raise AttributeError on Windows
    from signal import SIGTERM
    def terminate(process):
        kill(process.pid, SIGTERM)
except (AttributeError, ImportError):
    try:
        from win32api import TerminateProcess  # use win32api if available
        def terminate(process):
            TerminateProcess(int(process._handle), -1)
    except ImportError:
        def terminate(process):
            raise NotImplementedError  # define a dummy function

(समीक्षा पर: जॉन मिलिकिन ने क्या कहा।)


6

यह कई अन्य अनुकूलन की तरह है - आप गति के लिए कुछ पठनीयता का त्याग करते हैं। जैसा कि जॉन ने उल्लेख किया है, यदि आपने अपना प्रोफाइलिंग होमवर्क किया है और पाया है कि यह काफी उपयोगी पर्याप्त बदलाव है और आपको अतिरिक्त गति की आवश्यकता है, तो इसके लिए जाएं। संभवतः अन्य सभी आयातों के साथ एक नोट डालना अच्छा होगा:

from foo import bar
from baz import qux
# Note: datetime is imported in SomeClass below

4

मॉड्यूल इनिशियलाइज़ेशन केवल एक बार होता है - पहले आयात पर। यदि प्रश्न में मॉड्यूल मानक पुस्तकालय से है, तो आप इसे अपने कार्यक्रम में भी अन्य मॉड्यूल से आयात करेंगे। एक मॉड्यूल के रूप में प्राइमटाइम के रूप में प्रचलित है, यह भी अन्य मानक पुस्तकालयों के एक धसान के लिए निर्भरता की संभावना है। आयात विवरण बहुत कम खर्च होगा, क्योंकि मॉड्यूल की सूचना पहले ही हो चुकी होगी। यह सब इस बिंदु पर कर रहा है कि मौजूदा मॉड्यूल ऑब्जेक्ट को स्थानीय दायरे में बाँध रहा है।

युगल जो पठनीयता के तर्क के साथ जानकारी रखता है और मैं कहूंगा कि मॉड्यूल स्कोप पर आयात विवरण रखना सबसे अच्छा है।


4

मॉ के उत्तर और मूल प्रश्न को पूरा करने के लिए बस :

जब हमें परिपत्र निर्भरता से निपटना होता है तो हम कुछ "ट्रिक्स" कर सकते हैं। मान लिया जाये कि हम मॉड्यूल के साथ काम कर रहे हैं a.pyऔर b.pyयह शामिल हो x()और ख y()क्रमश। फिर:

  1. हम इनमें से एक को स्थानांतरित कर सकते हैं from imports मॉड्यूल में सबसे नीचे ।
  2. हम इनमें से एक को स्थानांतरित कर सकते हैं from imports फ़ंक्शन या विधि अंदर वास्तव में आयात की आवश्यकता है (यह हमेशा संभव नहीं है, जैसा कि आप इसे अन्य स्थानों से उपयोग कर सकते हैं)।
  3. हम दो from importsमें से एक को आयात करने के लिए बदल सकते हैं जो दिखता है:import a

तो, निष्कर्ष निकालना। यदि आप परिपत्र निर्भरता के साथ काम नहीं कर रहे हैं और उनसे बचने के लिए किसी प्रकार की चाल चल रहे हैं, तो इस सवाल के अन्य उत्तरों में पहले से ही बताए गए कारणों के कारण अपने सभी आयातों को शीर्ष पर रखना बेहतर है। और कृपया, जब इस "ट्रिक्स" में एक टिप्पणी शामिल हो, तो यह हमेशा स्वागत है! :)


4

पहले से दिए गए उत्कृष्ट उत्तरों के अलावा, यह ध्यान देने योग्य है कि आयात का स्थान केवल स्टाइल की बात नहीं है। कभी-कभी एक मॉड्यूल में अंतर्निहित निर्भरताएं होती हैं जिन्हें पहले आयात या आरंभ करने की आवश्यकता होती है, और एक शीर्ष-स्तरीय आयात से निष्पादन के आवश्यक आदेश का उल्लंघन हो सकता है।

यह मुद्दा अक्सर अपाचे स्पार्क के पायथन एपीआई में आता है, जहां आपको किसी भी pyspark पैकेज या मॉड्यूल को आयात करने से पहले SparkContext को इनिशियलाइज़ करना होगा। Psppark आयात को उस दायरे में रखना सबसे अच्छा है जहाँ SparkContext उपलब्ध होने की गारंटी है।


4

मैं पहले से ही पोस्ट किए गए बार-बार लोड-चेक के लिए वास्तविक लागत संख्या नहीं देखकर आश्चर्यचकित था, हालांकि उम्मीद करने के लिए कई अच्छे स्पष्टीकरण हैं।

यदि आप शीर्ष पर आयात करते हैं, तो आप लोड को हिट करते हैं, इससे कोई फर्क नहीं पड़ता। यह बहुत छोटा है, लेकिन आमतौर पर मिलीसेकंड में, नैनोसेकंड में नहीं।

यदि आप किसी फ़ंक्शन के भीतर आयात करते हैं, तो आप केवल लोड करने के लिए हिट लेते हैं अगर और जब उन कार्यों में से एक को पहले कहा जाता है। जैसा कि कई ने बताया है, यदि ऐसा बिल्कुल नहीं होता है, तो आप लोड समय बचाते हैं। लेकिन यदि फ़ंक्शन (एस) को बहुत अधिक कहा जाता है, तो आप एक दोहराया हालांकि बहुत छोटी हिट लेते हैं (यह जांचने के लिए कि यह लोड किया गया है, वास्तव में फिर से लोड करने के लिए नहीं)। दूसरी ओर, जैसा कि @aronasterling ने बताया कि आप थोड़ी बचत भी करते हैं क्योंकि एक फंक्शन में इंपोर्ट करने से फंक्शन को नाम की पहचान करने के लिए थोड़ी तेज़ी से लोकल वेरिएबल लुक्स का इस्तेमाल करना पड़ता है ( http://stackoverflow.com/questions/477096/python) आयात-कोडिंग-शैली / 4789963 # 4789963 )।

यहां एक साधारण परीक्षण के परिणाम हैं जो एक फ़ंक्शन के अंदर से कुछ चीजें आयात करते हैं। सूचित किया गया समय (एक 2.3 गीगाहर्ट्ज इंटेल कोर i7 पर पायथन 2.7.14 में) नीचे दिखाया गया है (बाद में कॉल करने से अधिक ले रहे 2 कॉल सुसंगत लगते हैं, हालांकि मुझे नहीं पता क्यों)।

 0 foo:   14429.0924 µs
 1 foo:      63.8962 µs
 2 foo:      10.0136 µs
 3 foo:       7.1526 µs
 4 foo:       7.8678 µs
 0 bar:       9.0599 µs
 1 bar:       6.9141 µs
 2 bar:       7.1526 µs
 3 bar:       7.8678 µs
 4 bar:       7.1526 µs

कोड:

from __future__ import print_function
from time import time

def foo():
    import collections
    import re
    import string
    import math
    import subprocess
    return

def bar():
    import collections
    import re
    import string
    import math
    import subprocess
    return

t0 = time()
for i in xrange(5):
    foo()
    t1 = time()
    print("    %2d foo: %12.4f \xC2\xB5s" % (i, (t1-t0)*1E6))
    t0 = t1
for i in xrange(5):
    bar()
    t1 = time()
    print("    %2d bar: %12.4f \xC2\xB5s" % (i, (t1-t0)*1E6))
    t0 = t1

लोड के जवाब में सीपीयू आवृत्ति स्केलिंग के कारण रनटाइम में परिवर्तन होने की संभावना है। सीपीयू घड़ी की गति बढ़ाने के लिए व्यस्त काम के एक सेकंड के साथ गति परीक्षण शुरू करना बेहतर है।
हान-क्वांग निएनहिउस

3

मुझे पूरा जवाब देने की इच्छा नहीं है, क्योंकि अन्य लोग पहले ही यह कर चुके हैं। मैं केवल एक उपयोग के मामले का उल्लेख करना चाहता हूं जब मुझे फ़ंक्शन के अंदर मॉड्यूल आयात करने के लिए विशेष रूप से उपयोगी लगता है। मेरा एप्लिकेशन प्लगइन्स के रूप में निश्चित स्थान पर संग्रहीत अजगर पैकेज और मॉड्यूल का उपयोग करता है। एप्लिकेशन स्टार्टअप के दौरान, एप्लिकेशन स्थान के सभी मॉड्यूल के माध्यम से चलता है और उन्हें आयात करता है, फिर यह मॉड्यूल के अंदर दिखता है और अगर यह प्लगइन्स के लिए कुछ बढ़ते बिंदु पाता है (मेरे मामले में यह एक विशिष्ट आधार वर्ग का एक उपवर्ग है जिसमें एक अद्वितीय है आईडी) यह उन्हें पंजीकृत करता है। प्लगइन्स की संख्या बड़ी है (अब दर्जनों, लेकिन शायद भविष्य में सैकड़ों) और उनमें से प्रत्येक का उपयोग बहुत कम ही किया जाता है। मेरे प्लगइन मॉड्यूल के शीर्ष पर तीसरे पक्ष के पुस्तकालयों का आयात करना एप्लिकेशन स्टार्टअप के दौरान थोड़ा जुर्माना था। विशेष रूप से कुछ थर्डपार्टी लाइब्रेरी आयात करने के लिए भारी हैं (उदाहरण के लिए प्लॉटली का आयात भी इंटरनेट से जुड़ने और कुछ डाउनलोड करने की कोशिश करता है जो लगभग एक सेकंड के स्टार्टअप को जोड़ रहा था)। आयातों का अनुकूलन करके (केवल उन कार्यों में जहां वे उपयोग किए जाते हैं) में कॉल करके मैं स्टार्टअप को 10 सेकंड से कुछ 2 सेकंड तक सिकोड़ने में कामयाब रहा। यह मेरे उपयोगकर्ताओं के लिए एक बड़ा अंतर है।

तो मेरा जवाब है, अपने मॉड्यूल के शीर्ष पर हमेशा आयात न करें।


3

यह दिलचस्प है कि एक भी उत्तर ने समानांतर प्रसंस्करण का उल्लेख नहीं किया है, जहां यह आवश्यक हो सकता है कि आयात कार्य में हो, जब क्रमबद्ध फ़ंक्शन कोड को अन्य कोर के चारों ओर धकेला जा रहा है, जैसे कि आईपीपरेल के मामले में।


1

किसी फंक्शन के अंदर वेरिएबल / लोकल स्कूप इम्पोर्ट करके परफॉर्मेंस गेन हो सकता है। यह फ़ंक्शन के अंदर आयातित चीज़ के उपयोग पर निर्भर करता है। यदि आप कई बार लूप कर रहे हैं और मॉड्यूल ग्लोबल ऑब्जेक्ट तक पहुंच रहे हैं, तो इसे स्थानीय के रूप में आयात करना मदद कर सकता है।

test.py

X=10
Y=11
Z=12
def add(i):
  i = i + 10

runlocal.py

from test import add, X, Y, Z

    def callme():
      x=X
      y=Y
      z=Z
      ladd=add 
      for i  in range(100000000):
        ladd(i)
        x+y+z

    callme()

run.py

from test import add, X, Y, Z

def callme():
  for i in range(100000000):
    add(i)
    X+Y+Z

callme()

लिनक्स पर एक समय एक छोटा लाभ दिखाता है

/usr/bin/time -f "\t%E real,\t%U user,\t%S sys" python run.py 
    0:17.80 real,   17.77 user, 0.01 sys
/tmp/test$ /usr/bin/time -f "\t%E real,\t%U user,\t%S sys" python runlocal.py 
    0:14.23 real,   14.22 user, 0.01 sys

असली दीवार घड़ी है। उपयोगकर्ता कार्यक्रम में समय है। सिस्टम कॉल के लिए sys समय है।

https://docs.python.org/3.5/reference/executionmodel.html#resolution-of-names


1

पठनीयता

स्टार्टअप प्रदर्शन के अलावा, स्थानीयकरण importबयानों के लिए एक पठनीयता तर्क दिया जाना है । उदाहरण के लिए मेरे मौजूदा पहले पायथन प्रोजेक्ट में 1296 के माध्यम से पायथन लाइन नंबर 1283 लें:

listdata.append(['tk font version', font_version])
listdata.append(['Gtk version', str(Gtk.get_major_version())+"."+
                 str(Gtk.get_minor_version())+"."+
                 str(Gtk.get_micro_version())])

import xml.etree.ElementTree as ET

xmltree = ET.parse('/usr/share/gnome/gnome-version.xml')
xmlroot = xmltree.getroot()
result = []
for child in xmlroot:
    result.append(child.text)
listdata.append(['Gnome version', result[0]+"."+result[1]+"."+
                 result[2]+" "+result[3]])

यदि importकथन फ़ाइल के शीर्ष पर था, तो मुझे Homeपता लगाने के लिए कि क्या ETथा , इसे लंबा करने के लिए स्क्रॉल करना होगा या प्रेस करना होगा । फिर मुझे रीडिंग कोड जारी रखने के लिए 1283 लाइन पर वापस नेविगेट करना होगा।

वास्तव में अगर import कथन फ़ंक्शन (या वर्ग) के शीर्ष पर था क्योंकि कई इसे जगह देंगे, पेजिंग और बैक डाउन की आवश्यकता होगी।

Gnome संस्करण संख्या प्रदर्शित करना शायद ही कभी होगा इसलिए importफ़ाइल के शीर्ष पर अनावश्यक स्टार्टअप लैग का परिचय दिया जाता है।


0

मैं अपने एक usecase का उल्लेख करना चाहूंगा, जो @John Millikin और @VK द्वारा उल्लिखित के समान है:

वैकल्पिक आयात

मैं ज्यूपिटर नोटबुक के साथ डेटा विश्लेषण करता हूं, और मैं सभी विश्लेषणों के लिए टेम्पलेट के रूप में समान आईपीथॉन नोटबुक का उपयोग करता हूं। कुछ अवसरों में, मुझे कुछ त्वरित मॉडल रन करने के लिए टेंसरफ़्लो को आयात करने की आवश्यकता होती है, लेकिन कभी-कभी मैं उन जगहों पर काम करता हूं जहां टेंसरफ़्लो स्थापित नहीं होता है / आयात करने के लिए धीमा है। उन मामलों में, मैं अपने टेंसरफ़्लो-आश्रित संचालन को एक सहायक कार्य में संलग्न करता हूं, उस फ़ंक्शन के अंदर टेंसरफ़्लो को आयात करता हूं, और इसे एक बटन पर बांधता हूं।

इस तरह, मैं आयात के लिए प्रतीक्षा किए बिना, या विफल होने पर बाकी कोशिकाओं को फिर से शुरू करने के लिए "पुनरारंभ-और-रन-सभी" कर सकता था।


0

यह एक आकर्षक चर्चा है। कई अन्य लोगों की तरह मैंने भी कभी इस विषय पर विचार नहीं किया था। मुझे अपने पुस्तकालयों में से एक में Django ORM का उपयोग करने के लिए इच्छुक होने के कारण कार्यों में आयात करने की अनुमति मिली है। मुझे django.setup()अपने मॉडल वर्गों को आयात करने से पहले कॉल करना था और क्योंकि यह आईओसी इंजेक्टर निर्माण के कारण फाइल के शीर्ष पर पूरी तरह से गैर-Django लाइब्रेरी कोड में खींचा जा रहा था।

मैं एक बिट के आसपास काट दिया और एक django.setup()एकल वर्ग के शीर्ष पर सिंगलटन कंस्ट्रक्टर और संबंधित आयात में डाल दिया । अब यह ठीक काम करता है लेकिन मुझे असहज कर देता है क्योंकि आयात शीर्ष पर नहीं थे और मुझे आयात के अतिरिक्त समय के बारे में भी चिंता होने लगी। फिर मैं यहां आया और बहुत दिलचस्पी के साथ हर किसी ने इसे पढ़ा।

मेरे पास एक लंबी सी ++ पृष्ठभूमि है और अब पायथन / साइथन का उपयोग करें। इस पर मेरी राय यह है कि जब तक यह आपको एक अपवित्र अड़चन का कारण नहीं बनाता है, तब तक फ़ंक्शन में आयात क्यों न करें। यह केवल वैरिएबल के लिए जगह घोषित करने जैसा है, इससे पहले कि आपको उनकी आवश्यकता हो। परेशानी यह है कि मेरे पास शीर्ष पर सभी आयातों के साथ हजारों लाइनें हैं! इसलिए मुझे लगता है कि मैं इसे अभी से करूंगा और विषम फ़ाइल को यहां और वहां बदलूंगा जब मैं गुजर रहा हूं और समय होगा।

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