2015-10-31 9 views
5

मैं निम्नलिखित है पैकेज संरचना के बिना एक सबपैकेज आयातअजगर दूसरों

package 
    __init__.py 
    sub1 
     __init__.py 
     foo.py  # Contains class Foo 
    sub2 
     __init__.py 
     bar.py  # Contains class Bar 

मैं चाहता हूँ बस import package और package.Foo और package.Bar के लिए सक्षम होने के लिए है, यानी मैं सबपैकेज उपयोगकर्ताओं के लिए पारदर्शी होना चाहते हैं।

पकड़ यह है कि उप 2 आयात करने में काफी समय लगता है, और कई उपयोगकर्ता उप 2 में सामान के बारे में बिल्कुल परवाह नहीं करते हैं और केवल सामान को उप 1 में चाहते हैं। इस प्रकार मैं चाहता हूं कि उपयोगकर्ता import package.sub1 या from package import sub1 से पर केवल आयात उप 1 और उप 2 के आयात को छोड़ने में सक्षम हों।

मैं जानता हूँ कि मैं package/__init__.py होने से पहले भाग प्राप्त कर सकते हैं शामिल

from .sub1 import * 
from .sub2 import * 

और package/sub1/__init__.py sub2 के लिए from .foo import Foo हो सकता है और इसी तरह हो रही है। हालांकि, यह हमेशा उप-1 और उप 2 आयात करेगा, भले ही उपयोगकर्ता केवल package.sub1 आयात करने का प्रयास करता हो।

अनुरूप बात यह है कि मैं package/__init__.py खाली होने और दूसरे के समान sub1/__init__.py का उपयोग करके दूसरे भाग को प्राप्त कर सकता हूं। हालांकि, बस कह रहे हैं कि import package उप 1 या उप 2 लोड नहीं करता है, इसलिए उपयोगकर्ताओं को उन्हें स्पष्ट रूप से लोड करना होगा और फिर package.sub1.Foo देखें।

आदर्श रूप से एक समाधान 2.7.10 और 3.5.0 दोनों में काम करेगा, लेकिन यदि दोनों संभव नहीं हैं तो मैं एक या दूसरे को स्वीकार करूंगा।

+1

में यह करने का आधिकारिक तरीका है एक बेहतर सवाल यह है कि आपके पास 'sub2' – jfs

+0

में मॉड्यूल स्तर पर एक लंबे समय से चलने वाला कोड क्यों है, वास्तव में, आपका प्रश्न है : "मैं 'आयात पैकेज' की तुलना में कड़ाई से कम चीजें करने के लिए 'import package.sub1' आयात करना चाहता हूं, है ना? कुछ अजीब हैक को पहले से बाइटकोड पढ़ने की तरह, मुझे लगता है कि यह संभव नहीं है।' आयात एबी 'को' ए आयात करना ' पहले। https: // दस्तावेज़ों के नीचे नोट करें।python.org/3.6/library/importlib.html (अंतिम कोड ब्लॉक, लाइन 15), 'import_module' एक पुनरावर्ती कार्य है। हालांकि, आप आसानी से एक तिहाई उप-पैकेज, 'package.everything' कर सकते हैं, जो वास्तव में उसी नामस्थान में' sub1' और 'sub2' आयात करेगा। – Veky

+0

@ वेकी: वास्तव में मैं वास्तव में क्या कर रहा हूं (ठीक है, 'पैकेज.ल', लेकिन पर्याप्त बंद करें) – Alec

उत्तर

0

आप अपने मॉड्यूल के __init__.py करने के लिए अपने शॉर्टकट जोड़ सकते हैं:

पैकेज/__ init__.py

__all__ = [ 
    ... add everything you want to be listed for this module 
    'Foo', 
    'Bar', 
    ... 
] 
from package.sub1.foo import Foo 
from package.sub2.bar import Bar 
अब

आप कॉल करने के लिए सक्षम होना चाहिए:

from package import Bar 
+0

यह 'पैकेज पैकेज' के बाद 'package.Bar' को सक्षम बनाता है लेकिन यह प्रश्न के" आलसी आयात "भाग को संभाल नहीं करता है। – jfs

4

LazyLoader कक्षा इस तरह की स्थिति के लिए प्रदान की जाती है: वास्तव में जब मॉड्यूल की लोडिंग को रोकना इसका आयात करने के बिंदु पर इस्तेमाल किया जाता है।

एक आलसी लोडर निर्माण करने के लिए आप दस्तावेज में उदाहरण का अनुसरण कर सकते हैं:

suffixes = importlib.machinery.SOURCE_SUFFIXES 
loader = importlib.machinery.SourceFileLoader 
lazy_loader = importlib.util.LazyLoader.factory(loader) 
finder = importlib.machinery.FileFinder(path, [(lazy_loader, suffixes)]) 

तो आप finder.find_spec का उपयोग एक मॉड्यूल की कल्पना प्राप्त करने के लिए कर सकते हैं और यह लोड करने के लिए Loader.create_module लिए परिणाम गुजरती हैं।

यह केवल एक मॉड्यूल के लिए मैन्युअल रूप से करने के लिए थोड़ा बोझिल है।

ध्यान दें कि "आलसी आयात पायथन" की खोज में आपको कुछ ऐसे समाधान मिलेंगे जिनमें विभिन्न समर्थक और विपक्ष हैं, जिनमें से कुछ python2.x में चलते हैं। हालांकि LazyLoader उपरोक्त वर्ग python3.5 +

+0

मैं इसे वास्तव में उप-पैकेज से सामान लोड करने के लिए नहीं मिल सकता। यदि 'sub2/__ init __। Py' में'bar आयात बार 'से है, तो यह' आयात त्रुटि: 'मॉड्यूल नाम नहीं है' पैकेज.बार ' यदि यह पूर्ण आयात का उपयोग करता है, तो मुझे' ValueError: मॉड्यूल ऑब्जेक्ट मिलता है 'पैकेज.sub2' को आलसी लोड के दौरान sys.modules में प्रतिस्थापित किया गया है ऐसा लगता है कि इसमें केवल उप 2 के नीचे प्रतीक होंगे, इसलिए मुझे अभी भी 'पैकेज.sub2.Bar' कहना होगा' पैकेज के बजाय भालू – Alec

+0

भविष्य में इसे देखने वाले किसी के लिए, यदि आप (मेरे जैसे) आलसी लोडर को काम करने के लिए नहीं मिल पा रहे हैं, तो मेरा समाधान सिर्फ 'पैकेज.ल' (या अगर आप पसंद करते हैं तो सब कुछ) था कि आयात सब कुछ, और शीर्ष स्तर पैकेज कुछ भी आयात नहीं करता है। अधिक चर्चा के लिए प्रश्न पर टिप्पणियां देखें – Alec

संबंधित मुद्दे