2011-09-06 7 views
7

मेरे पास कई फ़ंक्शन हैं जो फ़ाइलों से डेटा पार्स करते हैं, आमतौर पर परिणामों की एक सूची लौटाते हैं।मैं एक मूल्य वापस करना चाहता हूं और अपवाद बढ़ा सकता हूं, इसका मतलब है कि मैं कुछ गलत कर रहा हूं?

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

यह मुझे सफल डेटा वापस करने के लिए छोड़ देता है, लेकिन त्रुटि के कारण अपवाद भी उठाता है, जो स्पष्ट रूप से मैं नहीं कर सकता।

इस कोड पर विचार करें:

try: 
    parseResult = parse(myFile) 
except MyErrorClass, e: 
    HandleErrorsSomehow(str(e)) 

def parse(file): #file is a list of lines from an actual file 
    err = False 
    result = [] 

    for lines in file: 
     processedLine = Process(line) 
     if not processedLine: 
      err = True 
     else 
      result.append(processedLine) 
    return result 
    if err: 
     raise MyErrorClass("Something went wrong") 

जाहिर है पिछले तीन लाइनों कोई अर्थ नहीं है, लेकिन मैं यह करने के लिए एक अच्छा तरीका को समझ नहीं सकता। मुझे लगता है मैं return (err, result) कर सकता है, और यह

parseErr, parseResult = parse(file) 
if parseErr: 
    HandleErrorsSomehow() 

लेकिन लौटने त्रुटि कोड पर्याप्त अन-pythonic लगता है कहते हैं, अकेले त्रुटि कोड और वास्तविक परिणाम मूल्यों की tuples लौटने।

तथ्य यह है कि मुझे लगता है कि मैं ऐसा कुछ अजीब ऐसा करना चाहता हूं जो वास्तव में बहुत जटिल नहीं होना चाहिए, मुझे यह सोच रहा है कि मैं शायद कुछ गलत कर रहा हूं। क्या इस समस्या का कोई बेहतर समाधान है? या क्या कोई तरीका है कि मैं एक मूल्य वापस करने और एक ही समय में अपवाद बढ़ाने के लिए finally का उपयोग कर सकता हूं?

+0

इस मामले में, यदि कोई त्रुटि नहीं हुई है, तो मैं शायद 'त्रुटि सूचना' के साथ एक त्रुटि स्ट्रिंग होने के साथ एक tuple 'processedData, errorInformation' वापस कर दूंगा। एक और विकल्प कॉलबैक फ़ंक्शन का उपयोग करना होगा, अगर कोई त्रुटि होती है तो कुछ त्रुटि जानकारी के साथ बुलाया जाता है - यदि कॉलर परवाह नहीं है, तो यह कॉलबैक के रूप में 'कोई नहीं' पास कर सकता है। –

उत्तर

7

कोई भी नहीं कहता है कि केवल "त्रुटि" का इलाज करने का वैध तरीका अपवाद फेंकना है।

आपके डिज़ाइन में कॉलर जानकारी के दो टुकड़े चाहता है: (1) वैध डेटा, (2) क्या कोई त्रुटि हुई है (और शायद कुछ गलत हो गया है, तो यह एक उपयोगी त्रुटि संदेश प्रारूपित कर सकता है)। मूल्यों की एक जोड़ी लौटने के लिए यह एक पूरी तरह से वैध और उपरोक्त जमीन का मामला है।

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

+0

आपकी आखिरी वाक्य- यह करने के लिए एक बेहतर तरीका तलाशने के लिए मेरे मुख्य कारणों में से एक था। एक 'आउट पैरामीटर' का उपयोग करने के बारे में सोचा नहीं था। (क्या उनके पास एक बेहतर नाम है?) –

+0

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

+1

@CamJackson इस तरह की स्थितियों के लिए। मैंने अक्सर पाया है कि एक निर्दिष्ट कॉल हस्ताक्षर के साथ कॉलबैक पास करना कच्ची सूची को पार करने से बेहतर काम करता है। इस तरह से कार्यान्वयन को आंतरिक से दूर करना आसान है, साथ ही कॉलर को त्रुटियों को वापस पाने की परवाह नहीं होने पर स्टब कॉलबैक में डाल दिया जाता है। अक्सर, यह उस सूची के बाध्य '.append' विधि में गुजरने जितना आसान हो सकता है जिसे आप जोड़ना चाहते हैं। यह स्पष्ट करता है कि कुछ वापस पारित किया जा रहा है ("आउट" पैरा हमेशा स्पष्ट नहीं होते हैं), और कॉलर को त्रुटि के पल में जटिल प्रसंस्करण करने की अनुमति देता है। –

4

Emit a warning इसके बजाए, और कोड को यह तय करने दें कि इसे कैसे संभालें।

+0

वह प्यारा है। पता नहीं था कि मॉड्यूल मौजूद था। ऐसा लगता है कि चेतावनियों को अजगर के लॉगिंग से जोड़ा जा सकता है, जो बदले में गुई से जुड़ा हो सकता है। –

+0

यह अब देखकर आशाजनक लग रहा है। केवल एक चीज है, मैं ज्योथन का उपयोग कर रहा हूं, जिसमें 'चेतावनी.catch_warnings() 'प्रतीत नहीं होता है, इसलिए मुझे यकीन नहीं है कि मैं चेतावनियों को संभालने के लिए कैसे हूं। क्या मैं उन्हें अपवाद की तरह कोशिश कर सकता हूं? –

+0

हमम, मैंने [इस] (http://www.jython.org/jythonbook/en/1.0/ExceptionHandlingDebug.html#issuing-warnings) के माध्यम से पढ़ा है, लेकिन यह कुछ भी नहीं कहता है कि कॉलिंग फ़ंक्शन चेतावनियों को कैसे कैप्चर कर सकता है । जब तक मैं चेतावनियों को अपवादों में बदलने के लिए फ़िल्टर का उपयोग नहीं करता, लेकिन तब मैं वापस आ गया हूं जहां मैंने शुरू किया था, मैं नहीं हूं? क्या आप जानते हैं कि 'catch_warnings()' का उपयोग किये बिना चेतावनियों को कैसे संभाला जाए? –

0

मैं नेट दुनिया से आते हैं, ऐसा नहीं यकीन है कि यह कैसे अजगर में तब्दील हो ...

आपके जैसे मामलों मैं एक MyProcessingResults वापसी चाहते हैं (जहां एक कॉल में कई आइटम पर कार्रवाई करना चाहते हैं) में उद्देश्य यह है कि उदाहरण के लिए दो संग्रह आयोजित:

  • MyProcessingResults.ProcessedLines - सभी मान्य डेटा आप पार्स रखती है।
  • MyProcessingResults.Errors - सभी त्रुटियों को धारण करता है (इस धारणा पर कि आपके पास एक से अधिक हैं और आप उन सभी के बारे में स्पष्ट रूप से जानना चाहते हैं)।
+2

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

1

पैरामीटर के रूप में त्रुटि हैंडलर को पास करके, एक और संभावित डिज़ाइन नियंत्रण को उलटा करना है।

(इसके अलावा, आप की तरह अजगर को बताते हैं कि एक सूची में डेटा जमा करने के लिए किया है महसूस नहीं। यह पहले से ही जानता है। यह यहाँ एक सूची समझ काम करने के लिए मुश्किल नहीं है।)

def sample_handler(): 
    print "OMG, I wasn't expecting that; oh well." 

parseResult = parse(myFile, sample_handler) 

def parse(file, handler): #file is a list of lines from an actual file 
    result = [Process(line) for line in data] 
    if not all(result): handler() # i.e. if there are any false-ish values 
    result = filter(None, result) # remove false-ish values if any 
    return result 
+0

मेरी डेटा फ़ाइलों का प्रारूप मैं थोड़ा अधिक जटिल हूं, इसलिए मुझे वास्तव में सूची में मैन्युअल रूप से पुन: प्रयास करना होगा, लेकिन यह एक अच्छी विधि है। पाइथन सुखद आश्चर्य से भरा है! –

1

पर निर्भर करता है कॉलर डिजाइन। कॉलबैक का उपयोग करना उचित हो सकता है:

def got_line(line): 
    print 'Got valid line', line 

def got_error(error): 
    print 'got error', error 

def parse(file, line, error): 
    for lines in file: 
     processedLine = Process(line) 
     if not processedLine: 
      error(MyErrorClass("Something went wrong")) 
     else 
      line(processedLine) 


parse(some_file, got_line, got_error) 
1

मैं एक वैकल्पिक समाधान का प्रस्ताव देना चाहता हूं; एक वर्ग का उपयोग कर।

class MyParser(object): 
    def __init__(self): 
     self.warnings = [] 

    def parse(self, file): 
     ... 

अब पार्स समारोह warnings सूची में चेतावनी सेट कर सकते हैं, और यदि उपयोगकर्ता इस सूची की जांच कर सकते यदि वे ऐसा इच्छा।

जैसे ही मेरे कार्य "प्रक्रिया को संसाधित करें और मेरा मूल्य वापस करें" की तुलना में अधिक उन्नत होने लगते हैं, मुझे इसके बजाय कक्षा का उपयोग करने पर विचार करना पसंद है। यह एक ऑब्जेक्ट में संबंधित कोड की बड़ी क्लस्टरिंग के लिए बनाता है और यह अक्सर जानकारी के tuples लौटने वाले कार्यों की तुलना में क्लीनर कोड और सरल उपयोग के लिए बनाता है।