2009-01-18 11 views
12

मैं एक अजगर ढांचा विकसित कर रहा हूं जिसमें "एडॉन्स" अलग पैकेज के रूप में लिखा होगा। यानी .:एक ही नामस्थान में अलग पायथन पैकेज डाल रहे हैं?

import myframework 
from myframework.addons import foo, bar 

अब, ताकि इन एडऑन कोर ढांचे से अलग से वितरित किया जा सकता और myframework.addons नाम स्थान में इंजेक्शन है कि मैं क्या व्यवस्था करने के लिए कोशिश कर रहा हूँ है।

वर्तमान में मेरा सबसे अच्छा समाधान निम्न है। एक ऐड-ऑन {python_version}/site-packages/ में तैनात किया जाएगा, ताकि जैसे (सबसे अधिक संभावना:

fooext/ 
fooext/__init__.py 
fooext/myframework/ 
fooext/myframework/__init__.py 
fooext/myframework/addons/ 
fooext/myframework/addons/__init__.py 
fooext/myframework/addons/foo.py 

fooext/myframework/addons/__init__.py pkgutil पथ विस्तार कोड होगा:

import pkgutil 
__path__ = pkgutil.extend_path(__path__, __name__) 

समस्या यह है कि इस काम करने के लिए, PYTHONPATH इसमें fooext/ होने की आवश्यकता है, हालांकि इसमें केवल एक चीज है जो मूल स्थापित निर्देशिका है (सबसे अधिक संभावना है, उपर्युक्त site-packages)

इसका समाधानमें अतिरिक्त कोड होना हैजो sys.path ट्रान्सवर्स करेगा और एक myframework उप-पैकेज के साथ किसी भी मॉड्यूल की तलाश करेगा, इस मामले में यह इसे sys.path में जोड़ता है और सब कुछ काम करता है।

मुझे लगता है कि एडन फ़ाइलों को सीधे myframework/addons/ स्थान पर स्थापित करना एक और विचार है, लेकिन फिर यह विकास और तैनात नामस्थान भिन्न होगा।

क्या उपर्युक्त वितरण समस्या को पूरी तरह से या शायद एक अलग दृष्टिकोण को पूरा करने का एक बेहतर तरीका है?

उत्तर

4

वहाँ या इसके बाद के वितरण समस्या को पूरी तरह से करने के लिए एक अलग दृष्टिकोण एक बेहतर तरीका शायद यह पूरा करने के है?

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

उदाहरण के लिए आप एक पूरी तरह से अलग पैकेज में एक्सटेंशन कार्यक्षमता प्राप्त कर सकते हैं, लेकिन इसे एक विशिष्ट इंटरफ़ेस के माध्यम से कक्षाओं को अपने मूल ढांचे में इंजेक्ट करने की अनुमति दें। जैसे। myframework/_ _ init _ एक बुनियादी आवेदन आवरण युक्त _.py:

class MyFramework(object): 
    """A bare MyFramework, I only hold a person's name 
    """ 
    _addons= {} 
    @staticmethod 
    def addAddon(name, addon): 
     MyFramework._addons[name]= addon 

    def __init__(self, person): 
     self.person= person 
     for name, addon in MyFramework._addons.items(): 
      setattr(self, name, addon(self)) 

तो फिर तुम एक myexts/helloer.py में विस्तार कार्यक्षमता हो सकता था, कि अपने 'मालिक के लिए एक संदर्भ रखता है 'या' बाहरी 'myFramework वर्ग उदाहरण:

class Helloer(object): 
    def __init__(self, owner): 
     self.owner= owner 
    def hello(self): 
     print 'hello '+self.owner.person 

import myframework 
myframework.MyFramework.addAddon('helloer', Helloer) 

तो अब अगर आप सिर्फ "आयात myframework", आप केवल बुनियादी कार्यक्षमता मिलता है। लेकिन अगर आप "myexts.helloer आयात करें" तो आपको MyFramework.helloer.hello() को कॉल करने की क्षमता भी मिलती है। स्वाभाविक रूप से आप बुनियादी ढांचे के व्यवहार, और एक दूसरे के साथ बातचीत करने के लिए एडॉन्स के प्रोटोकॉल को भी परिभाषित कर सकते हैं। आप आंतरिक कक्षाओं जैसी चीजें भी कर सकते हैं जैसे ढांचे के उप-वर्ग को बंदर-पैच कक्षाओं के बिना अनुकूलित करने के लिए ओवरराइड कर सकते हैं जो अन्य अनुप्रयोगों को प्रभावित कर सकते हैं, यदि आपको जटिलता के स्तर की आवश्यकता होती है।

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

+0

नीचे एलेक का जवाब देखें। Setuptools के लिए कुछ ठीक है, जिसे entry_points कहा जाता है। –

0

ऐसा लगता है कि आप आयात हुक के साथ काफी अच्छी तरह से पूरा किए जा सकते हैं।

यह कस्टम लोडिंग कोड लिखने का एक तरीका है, जिसे पाइथन के डिफ़ॉल्ट लोडिंग तंत्र का उपयोग करने के बजाय सभी उप-पैकेजों और मॉड्यूल की लोडिंग करने के लिए पैकेज (या आपके मामले में ढांचे में) से जोड़ा जा सकता है। फिर आप लोडर को साइट पैकेज में आधार पैकेज के रूप में या अपने ढांचे के नीचे स्थापित कर सकते हैं।

जब लोडर के साथ एक पैकेज को जोड़ा जाता है (जिसे आवश्यक हो तो रिश्तेदार पथ पर हार्ड-कोड किया जा सकता है), तो यह हमेशा लोडर का उपयोग सभी एड-ऑन लोड करने के लिए करेगा। इसका लाभ PYTHONPATH की किसी भी झुकाव की आवश्यकता नहीं है, जो आम तौर पर जितना संभव हो उतना छोटा रखने के लायक है।

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

अधिक जानकारी यहां पाया जा सकता है:

http://www.python.org/dev/peps/pep-0302/

3

Setuptools में नाम से पैकेज "प्रविष्टि बिंदु" (फ़ंक्शन, ऑब्जेक्ट्स, जो कुछ भी) देखने की क्षमता है। ट्रैक इस तंत्र का उपयोग load its plugins पर करता है, और यह अच्छी तरह से काम करता है।

+0

मैं किसी अन्य के ऊपर एलेक की सिफारिश के लिए वोट दूंगा। प्रवेश बिंदु बिल्कुल इस के लिए डिज़ाइन किए गए थे, और दस्तावेज़ीकरण में डायनमिक प्लगइन लोडिंग का एक अच्छा उदाहरण है: https://pythonhosted.org/setuptools/setuptools.html#dynamic-discovery-of-services-and-plugins –

0

नामस्थान के लिए एक पूरी तरह से नए सेटअप नहीं है। Packaging namespace packages पर एक नज़र डालें। संक्षेप में, आपके पास तीन विकल्प हैं, इस आधार पर कि आप अपना कोड कितना पिछड़ा संगत होना चाहते हैं। एक प्रासंगिक पीईपी भी है, जो अन्य उत्तरों में उल्लिखित लोगों को पीछे छोड़ देता है: PEP 420

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