BaseException.message को Python 2.6 में चित्रित किया गया


177

जब मुझे निम्नलिखित उपयोगकर्ता द्वारा परिभाषित अपवाद का उपयोग करना होता है, तो मुझे एक चेतावनी मिलती है कि BaseException.message को Python 2.6 में हटा दिया गया है:

class MyException(Exception):

    def __init__(self, message):
        self.message = message

    def __str__(self):
        return repr(self.message)

यह चेतावनी है:

DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
self.message = message

इसमें गलत क्या है? पदावनति की चेतावनी से छुटकारा पाने के लिए मुझे क्या बदलना होगा?


9
कारणों के लिए पीईपी 352 देखें: python.org/dev/peps/pep-0352/#retracted-ideas
बाल्फा

जवाबों:


154

समाधान - लगभग किसी भी कोडिंग की आवश्यकता नहीं है

बस अपने अपवाद वर्ग को इनहेरिट करें Exceptionऔर संदेश को कंस्ट्रक्टर के पहले पैरामीटर के रूप में पास करें

उदाहरण:

class MyException(Exception):
    """My documentation"""

try:
    raise MyException('my detailed description')
except MyException as my:
    print my # outputs 'my detailed description'

आप कस्टम संदेश का उपयोग करने के लिए str(my)(या कम सुरुचिपूर्ण) my.args[0]का उपयोग कर सकते हैं।

पृष्ठभूमि

पायथन के नए संस्करणों में (2.6 से) हमें अपवाद से हमारी कस्टम अपवाद कक्षाएं विरासत में मिली हैं, जो ( एक्सटेप्शन से विरासत में मिला है, पायथन 2.5 से शुरू ) बेसएक्ससेप्शन से विरासत में मिला है। पीईपी 352 में पृष्ठभूमि का विस्तार से वर्णन किया गया है ।

class BaseException(object):

    """Superclass representing the base of the exception hierarchy.
    Provides an 'args' attribute that contains all arguments passed
    to the constructor.  Suggested practice, though, is that only a
    single string argument be passed to the constructor."""

__str__और __repr__पहले से ही एक सार्थक तरीके से लागू किया जाता है, विशेष रूप से केवल एक arg के मामले के लिए (जिसका उपयोग संदेश के रूप में किया जा सकता है)।

आपको दोहराने __str__या __init__लागू करने या बनाने की आवश्यकता नहीं है_get_message दूसरों द्वारा सुझाई गई ।


5
@Matt द्वारा सुझाए गए अपवाद को अपवाद के रूप में परिवर्तित करें
geekQ

8
strयदि एक यूनिकोड तर्क के साथ अपवाद का निर्माण किया गया था, तो ब्रेक का उपयोग करना : str(MyException(u'\xe5'))बढ़ जाता है UnicodeEncodeErrorunicodeइसके बजाय का उपयोग करना मूर्खतापूर्ण strनहीं है क्योंकि या तो unicode(MyException('\xe5'))यूनिकोडडब्लोसफ्रेम उठाता है। क्या इसका मतलब यह है कि अगर मुझे पहले से पता नहीं है कि क्या तर्क है strया unicode, मुझे उस जगह का उपयोग करना होगा .args[0]जहां मैंने पहले इस्तेमाल किया था .message?
कास्परड सिप

1
@kasperd लगभग सभी पायथन यूनिकोड मुद्दों की तरह, इसे यूनिकोड सैंडविच के साथ हल किया जा सकता है ।
रयान पी

3
@RyanP यह मानता है कि वास्तव में मेरा नियंत्रण है कि मैं क्या करता हूँ। यहाँ जीवन का एक तथ्य है जिसका मैंने सामना किया। मुझे कई तीसरे पक्ष के पुस्तकालयों से अपवादों को संभालना है। उनमें से कुछ यूनिकोड को अपने अपवादों में और कुछ पास को पास करते हैं। पुस्तकालयों में से एक का अपना वर्ग भी है जो यूनिकोड से विरासत में मिला है, लेकिन इसकी स्वयं की रीप विधि है, जो ऐनक के लिए आवश्यक के बजाय यूनिकोड देता है।
kasperd

1
मैंने बी.टी.वी. .messageहमारे प्रोजेक्ट के सभी उपयोग को बदलें .args[0], और इससे हमारे लिए कोई समस्या नहीं हुई है।
कास्परड

26

हां, यह Python 2.6 में पदावनत है क्योंकि यह Python 3.0 में दूर जा रहा है

BaseException class त्रुटि संदेश को संग्रहीत करने का एक तरीका प्रदान नहीं करता है। आपको इसे स्वयं लागू करना होगा। आप एक उपवर्ग के साथ ऐसा कर सकते हैं जो संदेश को संग्रहीत करने के लिए एक संपत्ति का उपयोग करता है।

class MyException(Exception):
    def _get_message(self): 
        return self._message
    def _set_message(self, message): 
        self._message = message
    message = property(_get_message, _set_message)

उम्मीद है की यह मदद करेगा


1
आप संदेश को कैसे बढ़ाएँगे? उनके कोड ने MyException ("कुछ संदेश") को कॉल करके सेट किए जा रहे संदेश को दिखाया
eric.frederich

मेरे उदाहरण में विधियां केवल संदेश संपत्ति को लागू करने के लिए हैं। कैसे संपत्ति का उपयोग किया जाता है कोडर तक है। इस मामले में, ओपी अपने कोड में पोस्ट किए गए init और str तरीकों का उपयोग करता है ।
सहस

1
एक गेटर / सेटर के बजाय एक सार्वजनिक चर का उपयोग करने पर विचार करें, अगर यह केवल दूसरे चर को पढ़ता है। @propertyजब आप वास्तव में इनकैप्सुलेशन की आवश्यकता होती है, तो आप हमेशा इसे बाद में एक सिंटैक्स में अपग्रेड कर सकते हैं ।
vdboor

2
@vdboor: वह डिप्रेशन @propertyचेतावनी को अक्षम करने के लिए उपयोग कर रहा है।
bukzor

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

9
class MyException(Exception):

    def __str__(self):
        return repr(self.args[0])

e = MyException('asdf')
print e

यह Python2.6 शैली में आपकी कक्षा है। नए अपवाद में मनमानी संख्या में तर्क होते हैं।


1
पुरानी अपवाद श्रेणी भी किसी भी तर्क को लेती है। आप पूरी तरह से संदेश की संपत्ति से बच सकते हैं जैसे कि आप क्या कर रहे हैं, लेकिन अगर वह आपके मौजूदा कोड को तोड़ देगा, तो आप अपनी संदेश संपत्ति को लागू करके समस्या को हल कर सकते हैं।
सहस

8

चेतावनी को कैसे दोहराया जाए

मुझे समस्या को स्पष्ट करने दें, क्योंकि कोई भी प्रश्न के नमूना कोड के साथ इसे दोहरा नहीं सकता है, यह पायथन 2.6 और 2.7 में चेतावनी को दोहराएगा, यदि आपके पास चेतावनी ( -Wध्वज के माध्यम से , PYTHONWARNINGSपर्यावरण चर, या चेतावनी मॉड्यूल ) है

>>> error = Exception('foobarbaz')
>>> error.message
__main__:1: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
'foobarbaz'

प्रयोग करना बन्द करें .message

मैं पसंद करता हूं repr(error), जो एक स्ट्रिंग देता है जिसमें त्रुटि प्रकार का नाम होता है, संदेश की पुनरावृत्ति, यदि एक है, और शेष तर्कों की पुनरावृत्ति है।

>>> repr(error)
"Exception('foobarbaz',)"

अभी भी उपयोग करते समय चेतावनी को खत्म करना .message

और जिस तरह से आप छुटकारा पा रहे हैं वह DeprecationWarningएक अंतर्निहित अपवाद को उपसंहार करना है जैसा कि पायथन डिजाइनरों का इरादा है:

class MyException(Exception):

    def __init__(self, message, *args):
        self.message = message
        # delegate the rest of initialization to parent
        super(MyException, self).__init__(message, *args)

>>> myexception = MyException('my message')
>>> myexception.message
'my message'
>>> str(myexception)
'my message'
>>> repr(myexception)
"MyException('my message',)"

.messageबिना सिर्फ विशेषता मिल रहा हैerror.message

यदि आप जानते हैं कि एक तर्क, एक संदेश, अपवाद के लिए है और वह है जो आप चाहते हैं, तो यह संदेश विशेषता से बचने और सिर्फ strत्रुटि लेने के लिए बेहतर है। एक उपवर्ग के लिए कहें Exception:

class MyException(Exception):
    '''demo straight subclass'''

और उपयोग:

>>> myexception = MyException('my message')
>>> str(myexception)
'my message'

इस उत्तर को भी देखें:

आधुनिक पायथन में कस्टम अपवाद घोषित करने का उचित तरीका?


4

जहां तक ​​मैं बता सकता हूं, बस संदेश विशेषता के लिए एक अलग नाम का उपयोग करने से आधार वर्ग के साथ संघर्ष से बचा जाता है, और इस तरह अप्रासंगिक चेतावनी बंद हो जाती है:

class MyException(Exception):

def __init__(self, message):
    self.msg = message

def __str__(self):
    return repr(self.msg)

मेरे लिए एक हैक की तरह लगता है।

हो सकता है कि कोई व्यक्ति यह स्पष्ट कर सके कि जब उप-संदेश स्पष्ट रूप से संदेश विशेषता को परिभाषित करता है तब भी चेतावनी क्यों जारी की जाती है। यदि आधार वर्ग में यह विशेषता नहीं है, तो कोई समस्या नहीं होनी चाहिए।


4

GeekQ के उत्तर से आगे बढ़ते हुए , पसंदीदा कोड प्रतिस्थापन इस बात पर निर्भर करता है कि आपको क्या करना है:

### Problem
class MyException(Exception):
    """My documentation"""

try:
    raise MyException('my detailed description')
except MyException as my:
    ### Solution 1, fails in Python 2.x if MyException contains 🔥
    # with UnicodeEncodeError: 'ascii' codec can't encode characters in position 24-25: ordinal not in range(128)
    print(my)  # outputs 'my detailed description'

### Solution 2
# Works in Python 2.x if exception only has ASCII characters,
# should always work in Python 3.x
str(my)

### Solution 3
# Required in Python 2.x if you need to handle non-ASCII characters,
# such as δσφφδσ (as pointed out by jjc) or emoji 🔥 💕 🎁 💯 🌹
# but does not work in Python 3.x
unicode(my)

कभी-कभी अपवादों में एक से अधिक तर्क होते हैं, इसलिए my.args[0] सभी प्रासंगिक जानकारी प्रदान करने की गारंटी नहीं है।

उदाहरण के लिए:

# Python 2.7
try:
    u'\u12345'.encode('utf-8').encode('utf-8')
except UnicodeDecodeError as e:
    print e.args[0]
    print e.args
    print str(e)

प्रिंट के रूप में उत्पादन:

ascii
('ascii', '\xe1\x88\xb45', 0, 1, 'ordinal not in range(128)')
'ascii' codec can't decode byte 0xe1 in position 0: ordinal not in range(128)

हालाँकि, यह एक संदर्भ संवेदनशील व्यापार बंद है, क्योंकि उदाहरण के लिए:

# Python 2.7
>>> str(SyntaxError())
'None'
# 'None' compares True which might not be expected

1
हाँ, इसे उखाड़ फेंके नहीं। के str(my)बजाय का उपयोग करें my.message
ईसाई लॉन्ग

1

Str (myexception) का उपयोग करने की सलाह से अजगर 2.7, उदा।

str(Exception(u'δσφφδσ'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)

:(

unicode(Exception(u'δσφφδσ')) 

अपेक्षा के अनुसार काम करता है, और उन मामलों में पसंद किया जाता है जहां त्रुटि स्ट्रिंग की कुछ सामग्री में उपयोगकर्ता इनपुट शामिल है


1

pzrq की पोस्ट का उपयोग करने के लिए कहते हैं:

str(e)

यह वही था जो मुझे चाहिए था।

(यदि आप यूनिकोड वातावरण में हैं, तो ऐसा प्रतीत होता है:

unicode(e)

काम करेगा, और यह एक गैर-यूनिकोड वातावरण में ठीक काम करता प्रतीत होता है)

Pzrq ने कई अन्य अच्छे सामानों के बारे में कहा, लेकिन मैं सभी अच्छे सामानों के कारण उनके उत्तर से चूक गया। चूँकि मेरे पास 50 अंक नहीं हैं, इसलिए मैं उनके उत्तर पर टिप्पणी नहीं कर सकता कि वह सरल समाधान पर ध्यान आकर्षित करने का प्रयास करता है जो काम करता है, और चूंकि मेरे पास 15 नहीं है मैं उस उत्तर को वोट नहीं दे सकता, लेकिन मैं पोस्ट कर सकता हूं (पीछे की ओर महसूस करता है, लेकिन ओह अच्छा) - तो यहाँ मैं पोस्ट कर रहा हूँ - शायद उसके लिए अंक खो दें ...

चूँकि मेरी बात pzrq के उत्तर पर ध्यान आकर्षित करने के लिए है, कृपया इस पर ध्यान न दें और इसे नीचे दिए गए सभी शब्दों में याद करें। इस पोस्ट की पहली कुछ पंक्तियाँ सबसे महत्वपूर्ण हैं।

मेरी कहानी:

मैं यहाँ जो समस्या लेकर आया था वह यह था कि क्या आप एक ऐसे वर्ग से अपवाद को पकड़ना चाहते हैं जिस पर आपका कोई नियंत्रण नहीं है - फिर क्या ??? मैं निश्चित रूप से सभी संभव वर्गों को उपवर्ग में नहीं जा रहा हूँ, मेरा कोड सभी संभावित अपवादों से एक संदेश प्राप्त करने में सक्षम होने के प्रयास में उपयोग करता है!

मैं उपयोग कर रहा था:

except Exception as e:
   print '%s (%s)' % (e.message,type(e))

जो, जैसा कि हम सभी अब जानते हैं, चेतावनी ओपी के बारे में पूछती है (जो मुझे यहां लाया था), और यह, जो कि इसे करने के तरीके के रूप में देता है:

except Exception as e:
   print '%s (%s)' % (str(e),type(e))

नहीं किया।

मैं एक यूनिकोड वातावरण में नहीं हूं, लेकिन jjc के उत्तर ने मुझे आश्चर्यचकित कर दिया, इसलिए मुझे यह प्रयास करना पड़ा। इस संदर्भ में यह बन जाता है:

except Exception as e:
   print '%s (%s)' % (unicode(e),type(e))

जो, मेरे आश्चर्य करने के लिए, बिल्कुल str (e) की तरह काम किया - तो अब यही मैं उपयोग कर रहा हूँ।

पता नहीं अगर 'str (e) / यूनिकोड (e)' स्वीकृत पायथन तरीका है ', और मुझे शायद पता चल जाएगा कि जब मैं 3.0 में पहुंचता हूं तो यह अच्छा क्यों नहीं है, लेकिन एक को उम्मीद है कि एक को संभालने की क्षमता मरने के बिना अप्रत्याशित अपवाद (*) और अभी भी इससे कुछ जानकारी मिलती है जो कभी दूर नहीं जाएगी ...

(*) हम्म। "अप्रत्याशित अपवाद" - मुझे लगता है कि मैंने अभी-अभी ठोकर खाई है!

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.