2013-08-06 9 views
21

मैं एक परियोजना के भीतर पाइथन स्क्रिप्ट का एक परिवार लिख रहा हूं; प्रत्येक स्क्रिप्ट परियोजना की उपनिर्देशिका के भीतर है, जैसे:पायथन: स्क्रिप्ट के परिवार के बीच सामान्य कोड साझा करना

projectroot 
    | 
    |- subproject1 
    | | 
    | |- script1.main.py 
    | `- script1.merger.py 
    | 
    |- subproject2 
    | | 
    | |- script2.main.py 
    | |- script2.matcher.py 
    | `- script2.merger.py 
    | 
    `- subproject3 
     | 
     |- script3.main.py 
     |- script3.converter.py 
     |- script3.matcher.py 
     `- script3.merger.py 

अब कई स्क्रिप्ट कुछ कोड साझा करते हैं। साझा कोड को प्रोजेक्ट का सबसे अच्छा हिस्सा माना जाता है, और कुछ ऐसा नहीं जो मैं अलग से संकलित करता हूं और पुस्तकालय को साइटवेइड पायथनपैथ में छोड़ देता हूं या छोड़ देता हूं। मैं उस कोड को विभिन्न स्थानों पर रख सकता हूं, जैसे कि projectroot निर्देशिका में, या projectroot की एक बच्चे निर्देशिका में common (शायद) कहा जाता है।

हालांकि, तरीके मैं अब तक के बारे में सोचा है के सबसे __init__.py फ़ाइलों खाली साथ अपने उप से बाहर संकुल बनाने और रिश्तेदार आयात का उपयोग कर (या प्रचुरता से हर subproject में sys.path साथ खिलवाड़ शामिल है। इससे भी बदतर है, यह एक पैकेज संरचना का निर्माण की तरह लगता है लिपियों के इस परिवार को अस्वीकार कर दिया PEP-3122 से निम्न चेतावनी के afoul चलाता है चारों ओर:

Attention! This PEP has been rejected. Guido views running scripts within a package as an anti-pattern.

तो एक पैकेज में स्क्रिप्ट विरोधी patternish, मैं कैसे एक तरह से जो एक ही में आम कोड रहता है में चीजों को सेट कर सकते हैं है प्रोजेक्ट? या यहां एक मॉड्यूल और पैकेज-आधारित सिस्टम स्वीकार्य है? सबसे साफ दृष्टिकोण कौन सा है? (एफडब्ल्यूआईडब्ल्यू मैं टी पसंद करूंगा o प्रोजेक्ट रूट निर्देशिका में shared.py या common.py जैसी फ़ाइल है, जो कि "असली" सबप्रोजेक्ट्स के लिए एक भाई बहन है।

+1

मेरा मानना ​​है कि django अपनी सभी स्क्रिप्ट चलाने के लिए केंद्रीकृत प्रविष्टि बिंदु 'manage.py' का उपयोग करता है। ऐसा कुछ करने से आप अपने 'सबप्रोजेक्टएक्स' को पैकेज में बदल सकते हैं, और "manage.py'" (एंट्री पॉइंट) स्क्रिप्ट के अंदर केंद्रीकृत आयात को संभाल सकते हैं। संकुल के रूप में, मेरा मानना ​​है कि यह आसानी से 'सामान्य' मॉड्यूल का समर्थन करेगा जहां आपकी साझा कार्यक्षमता लाइव हो सकती है। – dm03514

+1

मुझे विश्वास है कि [पीईपी -3122] होना चाहिए (https://www.python.org/dev/peps/pep-3122/), पीईपी -32122 नहीं। – user1071847

उत्तर

19

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

projectroot 
    |- script1.py # launcher scripts, see below for example code 
    |- script2.py 
    |- script3.py 
    | 
    |- common 
    | |- __init__.py 
    | |- merger.py # from other packages, use from ..common import merger to get this 
    | 
    |- subproject1 
    | |- __init__.py # this can be empty 
    | |- script1_main.py 
    | 
    |- subproject2 
    | |- __init__.py 
    | |- script2_main.py 
    | |- script2_matcher.py 
    | 
    |- subproject3 
     |- __init__.py 
     |- script3_main.py 
     |- script3_converter.py 
     |- script3_matcher.py 

लांचर स्क्रिप्ट बहुत आसान हो सकता है:

यहाँ संरचना, कैसा लगेगा अगर हम यह मान विभिन्न merger मॉड्यूल एक साझा संस्करण में पुनर्संशोधित किया जा सकता है

from subproject1 import script1_main 

if __name__ == "__main__": 
    script1_main.main() 

कि है, यह सब उचित "scriptN_main" मॉड्यूल आयात करता है और इसमें एक फ़ंक्शन चलाता है। स्क्रिप्ट स्टार्टअप गति के लिए एक साधारण स्क्रिप्ट का उपयोग करने के कुछ छोटे लाभ भी हो सकते हैं, क्योंकि main मॉड्यूल में संकलित बाइटकोड .pyc फ़ाइल में कैश किया जा सकता है, जबकि स्क्रिप्ट कभी कैश नहीं होती हैं।

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

+0

अच्छा लगता है, लेकिन 'common' तक पहुंचने के लिए मैं' subproject1.script1_main.py' के अंदर क्या कह सकता हूं? मैंने 'सामान्य आयात' करने की कोशिश की लेकिन 'फ़ाइल "मूवी/main.py", लाइन 1, आयात सामान्य आयात त्रुटि: कोई मॉड्यूल सामान्य नाम नहीं है' मैं मैन्युअल रूप से 'sys.path' सेट नहीं करना चाहता हूं। क्या मैं कुछ भूल रहा हूँ? –

+0

मुझे लगता है कि 'आयात ..common' काम करना चाहिए (एक स्पष्ट सापेक्ष आयात)। सुनिश्चित करें कि आप उप-प्रोजेक्ट फ़ाइलों को सीधे चलाने के बजाय शीर्ष स्तर पर स्क्रिप्ट चला रहे हैं, या हो सकता है कि यह पैकेज में न हो (आपको उस आयात के '..' हिस्से के बारे में एक त्रुटि मिलेगी मामला)। – Blckknght

+1

1. "सामान्य" निर्देशिका के अंदर '__init __। Py' फ़ाइल की आवश्यकता होती है। 2. आदेश 'आयात .. कमांड', जबकि 'से .. आयात सामान्य' सही है। इसके लिए प्रोजेक्टरूट में '__init __। Py' भी शामिल है और इसे मूल पैकेज की तरह आयात किया जाता है। 3. यदि आप प्रोजेक्टरूट आयात नहीं करते हैं लेकिन आप इसमें एक स्क्रिप्ट चलाते हैं, तो आप आसानी से 'सामान्य आयात' कर सकते हैं, क्योंकि '।' स्क्रिप्ट की निर्देशिका स्वचालित रूप से स्टार्टअप पर पाइथन पथ में जोड़ दी जाती है। – hynekcer

0

मेरी वरीयता एक अलग "बिन" या "स्क्रिप्ट" होगी निर्देशिका, के रूप में पुस्तकालयों/संकुल उप साथ:

projectroot 
    | 
    |- scripts 
    | 
    |- lib 
    | | 
    | `- matcher.py 
    | `- merger.py 
    | `- subproject1 
    | `- subproject2 
    | `- subproject3 

विचार किया जा रहा अपनी स्क्रिप्ट प्रत्येक किसी भी सामान्य संकुल के रूप में आवश्यक उप संदर्भित कर सकते हैं। और आपके उपप्रोजेक्ट एक दूसरे को आयात के साथ संदर्भित कर सकते हैं।

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

+0

मुझे वह विभाजन पसंद है, लेकिन मैंने प्रत्येक स्क्रिप्ट को एक अलग सबप्रोजेक्ट में शुरू करने के कारण दिखाने के लिए अपना उत्तर संपादित किया है - ऐसा इसलिए है क्योंकि प्रत्येक "स्क्रिप्ट" में कई भाग होते हैं। मैं कुछ साझा लाइब्रेरी कोड चाहता हूं - विभिन्न सबप्रोजेक्ट्स के बीच प्रत्येक स्क्रिप्ट द्वारा कार्य (और कक्षाएं) उपयोग योग्य। –

+0

मुझे लगता है कि साझा कोड libs की जड़ में जाना चाहिए। कृपया मेरा संपादन देखें। –

+1

मैट - 'स्क्रिप्ट' के अंतर्गत स्क्रिप्ट में 'lib' से कुछ भी आयात कैसे करेगा? आप सापेक्ष आयात का उपयोग नहीं कर पाएंगे, क्योंकि वे तकनीकी रूप से मॉड्यूल नहीं हैं। –

0

Please use setuptools वितरित करने के लिए दोनों लिपियों और पुस्तकालयों:

उदा

from setuptools import setup 

setup(
    # other arguments here... (e.g. packages/package_dir) 
    entry_points = { 
     'console_scripts': [ 
      'script1 = subproject1.script1:main', 
      'script2 = subproject2.script2:main', 
     ], 
    } 
) 

यदि आप पुस्तकालयों के रूप में अपना कोड लिख सकते हैं, और अपने प्रवेश बिंदु रखने के लिए अलग मॉड्यूल की आवश्यकता नहीं है तो यह आपके लिए टूल है। यदि आपके पास स्क्रिप्ट हैं, तो यह भी ठीक है, लेकिन आपको main फ़ंक्शन की आवश्यकता होगी जिसे आप संदर्भित कर सकते हैं (ऊपर उदाहरण देखें)

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