2014-10-24 24 views
7

मान लीजिए हम एक गैर-मौजूद विशेषता तक पहुँचने का प्रयास लापता वस्तु की पकड़ पाने के लिए कैसे:एक विशेषता

>>> {'foo': 'bar'}.gte('foo') # well, I meant “get”! 

पायथन के AttributeError केवल एक स्ट्रिंग समाप्त त्रुटि संदेश युक्त विशेषता args है: 'dict' object has no attribute 'gte'

और/या tracebacksys.last_traceback के साथ मॉड्यूल का उपयोग करके, वास्तविक dict ऑब्जेक्ट को पकड़ने का कोई तरीका है?

>>> offending_object = get_attributeerror_obj(sys.last_traceback) 
>>> dir(offending_object) 
[... 
'clear', 
'copy', 
'fromkeys', 
'get',  # ah, here it is! 
'items', 
...] 

संपादित करें:;)

के बाद से बिल्ली वैसे भी बैग से बाहर है, मैं अपने निष्कर्ष और कोड (कृपया इस का समाधान नहीं करते कृपया और PyPI के लिए प्रस्तुत,) साझा करेंगे AttributeErrorhere बनाया गया है, जो दर्शाता है कि मूल वस्तु से जुड़ा कोई स्पष्ट संदर्भ नहीं है।

यहाँ एक ही प्लेसहोल्डर समारोह के साथ कोड:

import sys 
import re 
import difflib 

AE_MSG_RE = re.compile(r"'(\w+)' object has no attribute '(\w+)'") 

def get_attributeerror_obj(tb): 
    ??? 

old_hook = sys.excepthook 

def did_you_mean_hook(type, exc, tb): 
    old_hook(type, exc, tb) 

    if type is AttributeError: 
     match = AE_MSG_RE.match(exc.args[0]) 
     sook = match.group(2) 

     raising_obj = get_attributeerror_obj(tb) 

     matches = difflib.get_close_matches(sook, dir(raising_obj)) 
     if matches: 
      print('\n\nDid you mean?', matches[0], file=sys.stderr) 

sys.excepthook = did_you_mean_hook 
+0

क्या आप डेवलपर से पूछने की तरह कुछ कहने का मतलब है "क्या आपका मतलब gte के बजाय मिलता है"? – karthikr

+3

रुबी के दोहराने की कोशिश कर रहा है [क्या आपका मतलब है ...] (http://www.yukinishijima.net/2014/10/21/did-you-mean-experience-in-ruby.html) कार्यक्षमता, आह? :-) – Kevin

+0

@ केविन: यह पीपीपीआई पर एक शानदार पैकेज होगा! [DidYouMean] (https://pypi.python.org/pypi/DidYouMean/) मौजूद है, लेकिन स्पेल चेकिंग टेक्स्ट के बारे में है, कोड नहीं। – ojdo

उत्तर

1

यह जवाब आप चाहते हैं नहीं है, लेकिन मैं बहुत यकीन है कि आप नहीं कर सकते हैं ... कम से कम sys.excepthook साथ नहीं कर रहा हूँ। ऐसा इसलिए है क्योंकि संदर्भ संख्याओं को कम किया गया है क्योंकि फ्रेम अवांछित है, इसलिए sys.excepthook से पहले ऑब्जेक्ट को एकत्रित कचरा होने के लिए यह पूरी तरह मान्य है। वास्तव में, यह सीपीथॉन में होता है:

import sys 

class X: 
    def __del__(self): 
     print("deleting") 

def error(): 
    X().wrong 

old_hook = sys.excepthook 
def did_you_mean_hook(type, exc, tb): 
    print("Error!") 
sys.excepthook = did_you_mean_hook 

error() 
#>>> deleting 
#>>> Error! 

ऐसा कहा जाता है, यह हमेशा ऐसा नहीं होता है। क्योंकि फ्रेम करने के लिए अपवाद वस्तु अंक, अपने कोड नज़र डालती है कि जैसे:

def error(): 
    x = X() 
    x.wrong 

x अभी तक एकत्र नहीं किया जा सकता है। x फ्रेम के स्वामित्व में है, और फ्रेम जिंदा है। लेकिन चूंकि मैंने पहले ही साबित कर दिया है कि इस वस्तु के लिए कोई स्पष्ट संदर्भ नहीं है, यह कभी भी स्पष्ट नहीं है कि क्या करना है। उदाहरण के लिए,

def error(): 
    foo().wrong 

या किसी वस्तु कि बच गया है, और पता लगाने के लिए केवल व्यवहार्य तरीका foo चलाने के लिए है हो सकता है हो सकता है नहीं ... लेकिन फिर भी आप दुष्प्रभावों के साथ समस्या है।

तो नहीं, यह संभव नहीं है। यदि आपको किसी भी लंबाई में जाने पर कोई फर्क नहीं पड़ता है, तो आप शायद लोड पर एएसटी को फिर से लिखना शुरू कर देंगे (FuckIt.py के समान)। हालांकि, आप ऐसा नहीं करना चाहते हैं।


मेरा सुझाव सभी ज्ञात वर्गों और उनके तरीकों के नाम प्राप्त करने के लिए एक लिटर का उपयोग करने का प्रयास करना होगा। आप वर्ग और गलत विधि प्राप्त करने के लिए ट्रेसबैक स्ट्रिंग को रिवर्स-इंजीनियर करने के लिए इसका उपयोग कर सकते हैं, और उसके बाद सुझाव खोजने के लिए एक अस्पष्ट मिलान चला सकते हैं।

+0

पर देखना चाहते हैं धन्यवाद, यह एक अच्छा जवाब है। यह मेरे नाम का उपयोग करके फ्रेम से कक्षा को पुनः प्राप्त करने के लिए भी मेरे पास नहीं हुआ, और आप अच्छी तरह से समझाते हैं कि ऑब्जेक्ट पुनर्प्राप्त करने योग्य क्यों नहीं है। मैंने सीपीथॉन के लिए एक फीचर अनुरोध दायर किया है और आपने जो किया है वह –

1

मेरे 2 सेंट जोड़कर मैंने सफलतापूर्वक (अब तक) DidYouMean-Python के लिए कुछ ऐसा करने की कोशिश की।

यह चाल यह है कि यह एक ऐसा मामला है जहां त्रुटि संदेश में वास्तव में आपके द्वारा अनुमानित जानकारी का अनुमान लगाने के लिए पर्याप्त जानकारी होती है। दरअसल, वास्तव में यहां क्या मायने रखता है कि आपने को dict ऑब्जेक्ट पर कॉल करने का प्रयास किया है: आपको ऑब्जेक्ट के प्रकार की आवश्यकता नहीं है।

आप {'foo': 'bar'}.get('foob') स्थिति बहुत संभाल करने के लिए जटिल काम होगा लिखा था और अगर कोई एक समाधान था मुझे पता है कि मुझे खुशी होगी अगर।

चरण एक

चेक करें कि आप एक AttributeError (हुक का पहला तर्क का प्रयोग करके) संभाल रहे हैं।

चरण दो

संदेश से संबंधित जानकारी (दूसरा तर्क का उपयोग कर देता है)। मैंने regexp के साथ ऐसा किया। कृपया ध्यान दें कि यह अपवाद आदि अजगर के संस्करण, वस्तु आप पर विधि बुला रहे हैं, के आधार पर कई रूपों ले जा सकते हैं

अब तक, मेरी regexp है: "^'?(\w+)'? (?:object|instance) has no attribute '(\w+)'$"

चरण तीन

उस प्रकार से संबंधित ऑब्जेक्ट प्राप्त करें (आपके मामले में 'dict') ताकि आप dir() पर कॉल कर सकें। एक गंदे समाधान का उपयोग केवल eval(type) होगा, लेकिन आप ट्रेस (आपके हुक के तीसरे तर्क) में जानकारी का पुन: उपयोग करके बेहतर और क्लीनर कर सकते हैं: ट्रेस के अंतिम तत्व में वह फ्रेम होता है जिसमें अपवाद होता है और उस फ्रेम में, प्रकार ठीक से परिभाषित किया गया था (या तो एक स्थानीय प्रकार, एक वैश्विक प्रकार या एक बिल्टिन के रूप में)।

एक बार आपके पास ऑब्जेक्ट होने के बाद, आपको केवल dir() पर कॉल करने की आवश्यकता है और आपको सबसे अधिक सुझाव देने वाले सुझाव निकालें।

अगर मुझे आपके द्वारा किए गए कार्यों के बारे में अधिक जानकारी चाहिए तो कृपया मुझे बताएं।

+0

'{' foo ':' bar '} जैसा ही होगा। प्राप्त करें (' foob ')' एक ऐसा मामला होगा जहां टाइप ट्रेसबैक फ्रेम में नहीं है ... मुझे उम्मीद है [पीईपी 437] (http://legacy.python.org/dev/peps/pep-0473/) लागू हो जाता है! –

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