আধুনিক পাইথনে কাস্টম ব্যতিক্রম ঘোষণা করার সঠিক উপায়?


1287

আধুনিক পাইথনে কাস্টম ব্যতিক্রম ক্লাসগুলি ঘোষণা করার উপযুক্ত উপায় কী? আমার প্রাথমিক লক্ষ্যটি অন্যান্য স্ট্যান্ডার্ড ব্যতিক্রম শ্রেণীর যে কোনও মানককে অনুসরণ করা হয়, যাতে (উদাহরণস্বরূপ) ব্যতিক্রমের মধ্যে আমি অন্তর্ভুক্ত থাকা কোনও অতিরিক্ত স্ট্রিংটি ব্যতিক্রম ধরা যাক কোনও সরঞ্জাম দ্বারা মুদ্রণ করা হয়।

"আধুনিক পাইথন" বলতে আমার অর্থ এমন কিছু যা পাইথন 2.5 তে চলবে তবে পাইথন 2.6 এবং পাইথন 3 এর জন্য 'সঠিক' হবে * * জিনিসগুলি করার উপায়। এবং "কাস্টম" দ্বারা আমি একটি ব্যতিক্রম বস্তু বলতে বোঝায় যা ত্রুটির কারণ সম্পর্কে অতিরিক্ত ডেটা অন্তর্ভুক্ত করতে পারে: একটি স্ট্রিং, সম্ভবত ব্যতিক্রমের সাথে সম্পর্কিত কিছু অন্যান্য স্বেচ্ছাসেবী অবজেক্ট।

পাইথন ২.6.২-এ নিম্নলিখিত অবমূল্যায়নের সতর্কবার্তাটি থেকে আমি বিভক্ত হয়েছি:

>>> class MyError(Exception):
...     def __init__(self, message):
...         self.message = message
... 
>>> MyError("foo")
_sandbox.py:3: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6

এটি পাগল বলে মনে হচ্ছে BaseExceptionযার নামযুক্ত বৈশিষ্ট্যগুলির একটি বিশেষ অর্থ রয়েছে message। আমি পিইপি -352 থেকে সংগ্রহ করি যে 2.5 এ এট্রিবিউটটির একটি বিশেষ অর্থ ছিল যা তারা হ্রাস করার চেষ্টা করছেন, তাই আমি অনুমান করি যে নামটি (এবং সেই একা) এখন নিষিদ্ধ? বিতৃষ্ণা।

আমি Exceptionকিছুটা যাদু প্যারামিটারও অস্পষ্টভাবে সচেতন args, তবে কীভাবে এটি ব্যবহার করতে হয় তা আমি কখনই জানতে পারি না। আমি নিশ্চিত না যে জিনিসগুলি এগিয়ে যাওয়ার সঠিক উপায় এটি; আমি অনলাইনে প্রচুর আলোচনার পরামর্শ দিয়েছিলাম যে তারা পাইথন 3-তে আর্গুমেন্টগুলি সরিয়ে দেওয়ার চেষ্টা করছে।

আপডেট: দুটি উত্তর ওভাররাইডিংয়ের পরামর্শ দিয়েছে __init__এবং __str__/ __unicode__/ __repr__। অনেকটা টাইপিংয়ের মতো মনে হচ্ছে, এটি কি প্রয়োজনীয়?

উত্তর:


1320

আমি প্রশ্নটি মিস করেছি, তবে কেন নয়:

class MyException(Exception):
    pass

সম্পাদনা করুন: কোনও কিছুকে ওভাররাইড করতে (বা অতিরিক্ত আরগগুলি পাস করতে), এটি করুন:

class ValidationError(Exception):
    def __init__(self, message, errors):

        # Call the base class constructor with the parameters it needs
        super(ValidationError, self).__init__(message)

        # Now for your custom code...
        self.errors = errors

এইভাবে আপনি দ্বিতীয় প্যারামে ত্রুটি বার্তাগুলির ডিকটি পাস করতে পারেন এবং এর সাথে পরে এটি পেতে পারেন e.errors


পাইথন 3 আপডেট: পাইথন 3+ এ আপনি এর থেকে আরও কিছুটা কমপ্যাক্ট ব্যবহার করতে পারেন super():

class ValidationError(Exception):
    def __init__(self, message, errors):

        # Call the base class constructor with the parameters it needs
        super().__init__(message)

        # Now for your custom code...
        self.errors = errors

35
তবে এর মতো সংজ্ঞায়িত একটি ব্যতিক্রম বাছাইযোগ্য হবে না; দেখতে আলোচনা এখানে stackoverflow.com/questions/16244923/...
jiakai

86
@ জিয়াকাই মানে "পিকলেবল"। :-)
রবিনো

1
ব্যবহারকারী-সংজ্ঞায়িত ব্যতিক্রমগুলির জন্য পাইথনের ডকুমেন্টেশন অনুসরণ করে, __init__ ফাংশনে উল্লিখিত নামগুলি ভুল। (স্ব, বার্তা, ত্রুটি) এর পরিবর্তে এটি (স্ব, অভিব্যক্তি, বার্তা)। অ্যাট্রিবিউট এক্সপ্রেশন হ'ল ইনপুট এক্সপ্রেশন যাতে ত্রুটি ঘটেছিল এবং বার্তাটি ত্রুটির ব্যাখ্যা।
ddleon

1
এটি একটি ভুল বোঝাবুঝি, @ ডডলিয়ন। আপনি যে দস্তাবেজের কথা উল্লেখ করছেন সেটি উদাহরণ কোনও নির্দিষ্ট ব্যবহারের ক্ষেত্রে। সাবক্লাসের কনস্ট্রাক্টর আর্গুমেন্টের নাম (না তাদের সংখ্যা) এর কোনও গুরুত্ব নেই।
অ্যাথাস্টার

498

আধুনিক পাইথন ব্যতিক্রমগুলি সহ আপনার গালিগালাজ করা .messageবা ওভাররাইড করা .__str__()বা .__repr__()এটির কোনও প্রয়োজন নেই any যদি আপনার ব্যতিক্রমগুলি উত্থাপিত হয় তখন আপনার সমস্ত কিছু যদি তথ্যমূলক বার্তা হয় তবে এটি করুন:

class MyException(Exception):
    pass

raise MyException("My hovercraft is full of eels")

এটি শেষ করে একটি ট্রেসব্যাক দেবে MyException: My hovercraft is full of eels

আপনি যদি ব্যতিক্রম থেকে আরও নমনীয়তা চান, আপনি একটি যুক্তি যুক্তি হিসাবে পাস করতে পারেন:

raise MyException({"message":"My hovercraft is full of animals", "animal":"eels"})

তবে কোনও exceptব্লকে সেই বিবরণগুলি পাওয়া কিছুটা জটিল। বিশদটি বিশদে সংরক্ষণ করা হয় args, যা একটি তালিকা। আপনার এই জাতীয় কিছু করা দরকার:

try:
    raise MyException({"message":"My hovercraft is full of animals", "animal":"eels"})
except MyException as e:
    details = e.args[0]
    print(details["animal"])

ব্যতিক্রমগুলিতে একাধিক আইটেমগুলিতে প্রবেশ করা এবং টিপল সূচকগুলির মাধ্যমে এগুলি অ্যাক্সেস করা এখনও সম্ভব, তবে এটি অত্যন্ত নিরুৎসাহিত (এবং এমনকি কিছুক্ষণ আগে অবমূল্যায়নের উদ্দেশ্যেও তৈরি হয়েছিল)। যদি আপনার একক টুকরো তথ্যের বেশি প্রয়োজন হয় এবং উপরের পদ্ধতিটি আপনার পক্ষে পর্যাপ্ত না হয় তবে আপনার টিউটোরিয়ালেException বর্ণিত সাবক্লাস করা উচিত ।

class MyError(Exception):
    def __init__(self, message, animal):
        self.message = message
        self.animal = animal
    def __str__(self):
        return self.message

2
"তবে ভবিষ্যতে এটি হ্রাস করা হবে" - এটি কি এখনও অবমূল্যায়নের জন্য উদ্দিষ্ট? পাইথন ৩.7 এখনও আনন্দের সাথে গ্রহণ করেছে বলে মনে হচ্ছে Exception(foo, bar, qux)
mtraceur

রূপান্তরের ব্যথার কারণে শেষ চেষ্টা ব্যর্থ হওয়ার পরে এটি চিত্রিত করার জন্য সাম্প্রতিক কোনও কাজ দেখেনি, তবে এখনও ব্যবহারটি নিরুৎসাহিত করা হয়েছে। আমি প্রতিফলিত করতে আমার উত্তর আপডেট করব।
frnknstn

@ ফ্রনকনস্টন, কেন এটি নিরুৎসাহিত করা হচ্ছে? আমার কাছে দেখতে খুব সুন্দর একটা প্রতিমা বলে মনে হচ্ছে।
নেভেজ

2
@ শুরু করার আগে, ব্যতিক্রম তথ্য সংরক্ষণ করতে টিপলস ব্যবহার করার জন্য অভিধানটি ব্যবহার করার কোনও সুবিধা নেই। আপনি যদি ব্যতিক্রম পরিবর্তনের পিছনে যুক্তিতে
frnknstn

পিইপি 352 এর প্রাসঙ্গিক বিভাগটি " রিট্র্যাক্ট আইডিয়া"
লিবারফোর্স

196

"আধুনিক পাইথনে কাস্টম ব্যতিক্রমগুলি ঘোষণা করার উপযুক্ত উপায়?"

এটি ঠিক আছে, যদি না আপনার ব্যতিক্রম সত্যিই আরও নির্দিষ্ট ব্যতিক্রমগুলির এক প্রকার:

class MyException(Exception):
    pass

বা আরও ভাল (সম্ভবত নিখুঁত), passকোনও ডক্ট্রাস্টিং দেওয়ার পরিবর্তে :

class MyException(Exception):
    """Raise for my specific kind of exception"""

সাবক্লাসিং ব্যতিক্রম সাবক্লাস

ডক্স থেকে

Exception

সমস্ত অন্তর্নির্মিত, অ-সিস্টেম-বহির্গমন ব্যতিক্রমগুলি এই শ্রেণি থেকে প্রাপ্ত। সমস্ত ব্যবহারকারী-সংজ্ঞায়িত ব্যতিক্রমগুলিও এই শ্রেণি থেকে নেওয়া উচিত।

এর অর্থ হ'ল যদি আপনার ব্যতিক্রমটি আরও নির্দিষ্ট ব্যতিক্রমগুলির একধরণের হয় তবে জেনেরিকের পরিবর্তে সাবক্লাসটি সেই ব্যতিক্রম Exception(এবং ফলাফলটি Exceptionডক্সের পরামর্শ অনুযায়ী আপনি এখনও পেতে পারেন )। এছাড়াও, আপনি কমপক্ষে একটি ডাস্ট্রিং সরবরাহ করতে পারেন (এবং passকীওয়ার্ডটি ব্যবহার করতে বাধ্য করা হবে না ):

class MyAppValueError(ValueError):
    '''Raise when my specific value is wrong'''

আপনি একটি কাস্টম দিয়ে নিজেকে তৈরি বৈশিষ্ট্য সেট করুন __init__। অবস্থানগত আর্গুমেন্ট হিসাবে ডিক পাস করা এড়িয়ে চলুন, আপনার কোডের ভবিষ্যতের ব্যবহারকারীরা আপনাকে ধন্যবাদ জানাবে। আপনি যদি অবহেলিত বার্তার বৈশিষ্ট্যটি ব্যবহার করেন তবে এটিকে নিজেকে নির্ধারণ করা এড়াতে পারবেন DeprecationWarning:

class MyAppValueError(ValueError):
    '''Raise when a specific subset of values in context of app is wrong'''
    def __init__(self, message, foo, *args):
        self.message = message # without this you may get DeprecationWarning
        # Special attribute you desire with your Error, 
        # perhaps the value that caused the error?:
        self.foo = foo         
        # allow users initialize misc. arguments as any other builtin Error
        super(MyAppValueError, self).__init__(message, foo, *args) 

আপনার নিজের লেখার দরকার নেই __str__বা __repr__। অন্তর্নির্মিতগুলি খুব সুন্দর, এবং আপনার সমবায় উত্তরাধিকার নিশ্চিত করে যে আপনি এটি ব্যবহার করেছেন।

শীর্ষ উত্তরের সমালোচনা

আমি প্রশ্নটি মিস করেছি, তবে কেন নয়:

class MyException(Exception):
    pass

আবার উপরের সমস্যাটি হ'ল এটি ধরার জন্য আপনাকে অবশ্যই এটির নাম রাখতে হবে (অন্য কোথাও তৈরি হলে এটি আমদানি করতে হবে) বা এক্সেসপেশন ধরতে হবে (তবে আপনি সম্ভবত সব ধরণের ব্যতিক্রম পরিচালনা করতে প্রস্তুত নন, এবং আপনার কেবলমাত্র ব্যতিক্রমগুলি ধরা উচিত যা আপনি পরিচালনা করতে প্রস্তুত)। নীচের মতো অনুরূপ সমালোচনা, তবে অতিরিক্ত superএটির মাধ্যমে আরম্ভ করার উপায় নয় এবং আপনি DeprecationWarningবার্তাটির বৈশিষ্ট্যে অ্যাক্সেস করলে একটি পাবেন :

সম্পাদনা করুন: কোনও কিছুকে ওভাররাইড করতে (বা অতিরিক্ত আরগগুলি পাস করতে), এটি করুন:

class ValidationError(Exception):
    def __init__(self, message, errors):

        # Call the base class constructor with the parameters it needs
        super(ValidationError, self).__init__(message)

        # Now for your custom code...
        self.errors = errors

এইভাবে আপনি দ্বিতীয় প্যারামে ত্রুটি বার্তাগুলির ডিকটি পাস করতে পারেন এবং এটিতে eEerferences দিয়ে পরে পেতে পারেন

এটির জন্য ঠিক দুটি যুক্তিও পাস করতে হবে (দিক থেকে বাদে self) আর কিছু নয়, কমও নয়। এটি একটি আকর্ষণীয় প্রতিবন্ধকতা যা ভবিষ্যতের ব্যবহারকারীরা প্রশংসা করতে পারে না।

সরাসরি হতে - এটি লিসকোভ স্থান পরিবর্তনযোগ্যতা লঙ্ঘন করে ।

আমি উভয় ত্রুটি প্রদর্শন করব:

>>> ValidationError('foo', 'bar', 'baz').message

Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    ValidationError('foo', 'bar', 'baz').message
TypeError: __init__() takes exactly 3 arguments (4 given)

>>> ValidationError('foo', 'bar').message
__main__:1: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
'foo'

তুলনা করা:

>>> MyAppValueError('foo', 'FOO', 'bar').message
'foo'

2
হ্যালো 2018 থেকে! BaseException.messageপাইথন 3 এ চলে গেছে, তাই সমালোচনাটি কেবল পুরানো সংস্করণগুলির জন্য রয়েছে, তাই না?
কোস

5
@ কোস লিসকোভ সাবস্টিটিউবিলিটি সম্পর্কে সমালোচনা এখনও বৈধ। "বার্তা" হিসাবে প্রথম যুক্তির শব্দার্থবিজ্ঞানগুলিও তর্কযোগ্যভাবে প্রশ্নবিদ্ধ, তবে আমি মনে করি না যে আমি বিষয়টি নিয়ে তর্ক করব। আমার আরও ফ্রি সময় পেলে আমি এটির আরও চেহারা দেব।
অ্যারন হল

1
FWIW, পাইথন 3 জন্য (3.6+ জন্য অন্তত), একটি পুনরায় সংজ্ঞায়িত করবে __str__পদ্ধতির MyAppValueErrorউপর নির্ভর পরিবর্তে messageঅ্যাট্রিবিউট
Jacquot

1
@ অ্যারনহল আপনি কি ব্যতিক্রমের পরিবর্তে উপ-শ্রেণিবদ্ধকরণের ভ্যালুআরারের সুবিধাতে প্রসারিত করতে পারেন? আপনি উল্লেখ করেছেন যে ডক্স দ্বারা এটি বোঝানো হয়েছে তবে সরাসরি পাঠটি সেই ব্যাখ্যাকে সমর্থন করে না এবং ব্যবহারকারী-সংজ্ঞায়িত ব্যতিক্রমগুলির অধীনে পাইথন টিউটোরিয়ালে এটি স্পষ্টতই এটি ব্যবহারকারীদের পছন্দ করে তোলে: "ব্যতিক্রমগুলি সাধারণত ব্যতিক্রম শ্রেণি থেকে নেওয়া উচিত, হয় প্রত্যক্ষ বা পরোক্ষভাবে। " সুতরাং আপনার মতামত ন্যায়সঙ্গত কিনা তা বুঝতে আগ্রহী, দয়া করে।
অস্ট্রগার্ড

1
@ostergaard এই মুহুর্তে সম্পূর্ণরূপে উত্তর দিতে পারে না, তবে সংক্ষেপে, ব্যবহারকারী ধরার অতিরিক্ত বিকল্প পান ValueError। এটি মান ত্রুটিগুলির ক্যাটাগরিতে থাকলে এটি বোঝা যায়। যদি এটি মান ত্রুটিগুলির ক্যাটাগরিতে না থাকে তবে আমি এর বিরুদ্ধে শব্দার্থবিদ্যায় তর্ক করব। প্রোগ্রামারের অংশে কিছু উপকার এবং যুক্তির অবকাশ আছে, তবে প্রযোজ্য ক্ষেত্রে আমি অনেক নির্দিষ্টতা পছন্দ করি। আমি শীঘ্রই বিষয়টিকে আরও ভালভাবে মোকাবেলায় আমার উত্তর আপডেট করব।
অ্যারন হল

50

যদি কোনও বনাম আরও গুণাবলী ব্যবহার করা হয় তবে ব্যতিক্রমগুলি ডিফল্টরূপে কীভাবে কাজ করে তা দেখুন (ট্রেসব্যাকগুলি বাদ দেওয়া হয়েছে):

>>> raise Exception('bad thing happened')
Exception: bad thing happened

>>> raise Exception('bad thing happened', 'code is broken')
Exception: ('bad thing happened', 'code is broken')

সুতরাং আপনি একটি সামঞ্জস্যপূর্ণ উপায়ে নিজেই ব্যতিক্রম হিসাবে কাজ করে এক ধরণের " ব্যতিক্রম টেম্পলেট " রাখতে চান:

>>> nastyerr = NastyError('bad thing happened')
>>> raise nastyerr
NastyError: bad thing happened

>>> raise nastyerr()
NastyError: bad thing happened

>>> raise nastyerr('code is broken')
NastyError: ('bad thing happened', 'code is broken')

এটি এই সাবক্লাসের সাহায্যে সহজেই করা যায়

class ExceptionTemplate(Exception):
    def __call__(self, *args):
        return self.__class__(*(self.args + args))
# ...
class NastyError(ExceptionTemplate): pass

এবং যদি আপনি সেই ডিফল্ট টিপল-জাতীয় উপস্থাপনাটি পছন্দ __str__না করেন তবে ExceptionTemplateক্লাসে কেবল পদ্ধতি যুক্ত করুন , যেমন:

    # ...
    def __str__(self):
        return ': '.join(self.args)

এবং আপনার হবে

>>> raise nastyerr('code is broken')
NastyError: bad thing happened: code is broken

32

পাইথন ৩.৮ (2018, https://docs.python.org/dev/whatsnew/3.8.html ) হিসাবে, প্রস্তাবিত পদ্ধতিটি এখনও:

class CustomExceptionName(Exception):
    """Exception raised when very uncommon things happen"""
    pass

দস্তাবেজ করতে ভুলবেন না, কেন একটি কাস্টম ব্যতিক্রম প্রয়োজনীয়?

আপনার যদি প্রয়োজন হয় তবে আরও ডেটা সহ ব্যাতিক্রমের উপায়:

class CustomExceptionName(Exception):
    """Still an exception raised when uncommon things happen"""
    def __init__(self, message, payload=None):
        self.message = message
        self.payload = payload # you could add more args
    def __str__(self):
        return str(self.message) # __str__() obviously expects a string to be returned, so make sure not to send any other data types

এবং তাদের মত আন:

try:
    raise CustomExceptionName("Very bad mistake.", "Forgot upgrading from Python 1")
except CustomExceptionName as error:
    print(str(error)) # Very bad mistake
    print("Detail: {}".format(error.payload)) # Detail: Forgot upgrading from Python 1

payload=Noneএটি আচার-সক্ষম করতে গুরুত্বপূর্ণ। এটি ডাম্প করার আগে আপনাকে কল করতে হবে error.__reduce__()। লোডিং প্রত্যাশার মতো কাজ করবে।

আপনার returnযদি কোনও বাহ্যিক কাঠামোতে স্থানান্তরিত করার জন্য আরও বেশি ডেটা প্রয়োজন হয় তবে অজগর বিবৃতি ব্যবহার করে কোনও সমাধান খোঁজার ক্ষেত্রে আপনার তদন্ত করা উচিত । এটি আমার কাছে পরিষ্কার / আরও পাইথোনিক বলে মনে হচ্ছে। অ্যাডভান্সড ব্যতিক্রমগুলি জাভাতে খুব বেশি ব্যবহৃত হয়, যা কোনও কাঠামো ব্যবহার করার সময় এবং সমস্ত সম্ভাব্য ত্রুটিগুলি ধরা পরে কখনও কখনও বিরক্তিকর হতে পারে।


1
খুব কমপক্ষে, বর্তমান দস্তাবেজগুলি ইঙ্গিত দেয় যে এটি করার উপায় (কমপক্ষে ছাড়া ছাড়া __str__) অন্যান্য উত্তরগুলি ব্যবহার করে না super().__init__(...)Just কেবলমাত্র একটি লজ্জা যা আরও ভাল "ডিফল্ট" সিরিয়ালাইজেশনের জন্য ওভাররাইড করে __str__এবং __repr__সম্ভবত প্রয়োজনীয়।
কেভেলারার

2
সৎ প্রশ্ন: ব্যতিক্রমের জন্য અથা-সক্ষম হওয়া কেন গুরুত্বপূর্ণ? ডাম্পিং এবং লোডিং ব্যতিক্রমগুলির জন্য ব্যবহারের ক্ষেত্রে কী কী?
রোল শ্রোইভেন 19

1
@ রোলস্ক্রোয়েভেন: আমাকে একবার কোডের সমান্তরাল করতে হয়েছিল। সূক্ষ্ম একক প্রক্রিয়া চালান, তবে এর কয়েকটি শ্রেণীর দিকগুলি সিরিয়ালযোগ্য ছিল না (ল্যাম্বডা ফাংশনটি বস্তু হিসাবে পাস হচ্ছে)। এটি নির্ধারণ করতে এবং এটি ঠিক করার জন্য আমাকে কিছু সময় নিয়েছে। এর অর্থ কেউ পরে আপনার কোডটি সিরিয়ালীকরণ হতে পারে, এটি করতে অক্ষম হবে এবং কেন এটি খনন করতে হবে ... আমার সমস্যাটি অনাদায়ী ত্রুটি ছিল না, তবে আমি দেখতে পাচ্ছি এটি একইরকম সমস্যা সৃষ্টি করছে।
লজিকঅ্যানস্ট্রাকশন

17

আপনার বার্তাটি ব্যবহার করার পরিবর্তে ওভাররাইড __repr__বা __unicode__পদ্ধতিগুলি উচিত , আপনি ব্যতিক্রমগুলি নির্মাণের সময় সরবরাহ করা আরগগুলি argsব্যতিক্রমের অবজেক্টের বৈশিষ্ট্যে থাকবে।


7

না, "বার্তা" নিষিদ্ধ নয়। এটি স্রেফ অবমূল্যায়িত। আপনার আবেদন বার্তা ব্যবহার করে ভাল কাজ করবে। তবে আপনি অবশ্যই অবমূল্যায়ন ত্রুটি থেকে মুক্তি পেতে চাইতে পারেন।

আপনি যখন নিজের অ্যাপ্লিকেশনটির জন্য কাস্টম এক্সেপশন ক্লাস তৈরি করেন, তাদের মধ্যে অনেকগুলি কেবল ব্যতিক্রম থেকে সাবক্লাস করেন না, তবে অন্যদের কাছ থেকে যেমন ভ্যালুয়েরর বা অনুরূপ। তারপরে আপনাকে তাদের ভেরিয়েবলগুলির ব্যবহারের সাথে খাপ খাইয়ে নিতে হবে।

এবং আপনার অ্যাপ্লিকেশনটিতে যদি আপনার অনেকগুলি ব্যতিক্রম থাকে তবে তাদের সবার জন্য একটি সাধারণ কাস্টম বেস শ্রেণি রাখা সাধারণত ভাল ধারণা, যাতে আপনার মডিউলগুলির ব্যবহারকারীরা করতে পারেন

try:
    ...
except NelsonsExceptions:
    ...

এবং সেক্ষেত্রে আপনি এটি করতে পারেন __init__ and __str__ সেক্ষেত্রে আপনি সেখানে প্রয়োজনীয় , তাই আপনাকে প্রতিটি ব্যতিক্রমের জন্য এটি পুনরাবৃত্তি করতে হবে না। তবে কেবল মেসেজটি পরিবর্তনশীলকে কল করা মেসেজের চেয়ে অন্য কিছু করে।

যে কোনও ক্ষেত্রে, আপনার কেবলমাত্র প্রয়োজন __init__ or __str__যদি আপনি ব্যতিক্রম নিজে যা করেন তার থেকে আলাদা কিছু করেন। এবং কারণ যদি অবমূল্যায়ন হয় তবে আপনার তখন উভয়েরই দরকার হয় অথবা আপনি একটি ত্রুটি পান। এটি প্রতি ক্লাসে আপনার অতিরিক্ত কোডের দরকার নেই। ;)


এটি আকর্ষণীয় যে জাজানো ব্যতিক্রমগুলি কোনও সাধারণ বেস থেকে উত্তরাধিকারসূত্রে আসে না। docs.djangoproject.com/en/2.2/_modules/django/core/exferences নির্দিষ্ট অ্যাপ্লিকেশন থেকে সমস্ত ব্যতিক্রম যখন ধরা দরকার তখন আপনার কি উদাহরণ রয়েছে? (সম্ভবত এটি কেবল কিছু নির্দিষ্ট ধরণের অ্যাপ্লিকেশনের জন্যই কার্যকর)।
ইয়ারোস্লাভ নিকিতেনকো

আমি julien.danjou.info/python-exception-guide এই বিষয়টিতে একটি ভাল নিবন্ধ পেয়েছি । আমি মনে করি ব্যতিক্রমগুলি প্রাথমিকভাবে ডোমেন-ভিত্তিক সাবস্ক্লাস করা উচিত, অ্যাপ্লিকেশন ভিত্তিক নয়। যখন আপনার অ্যাপ্লিকেশনটি এইচটিটিপি প্রোটোকল সম্পর্কিত, আপনি HTTPError থেকে প্রাপ্ত হন। যখন আপনার অ্যাপ্লিকেশনটির অংশটি টিসিপি হয়, আপনি সেই অংশটির ব্যতিক্রমগুলি টিসিপিআরারের থেকে প্রাপ্ত করেন। তবে যদি আপনার অ্যাপ্লিকেশনটি অনেকগুলি ডোমেন (ফাইল, অনুমতিগুলি, ইত্যাদি) বিস্তৃত করে তবে মাইবেসএক্সেপশন হ্রাস পাওয়ার কারণ। নাকি এটি 'স্তর লঙ্ঘন' থেকে রক্ষা করতে হবে?
ইয়ারোস্লাভ নিকিতেনকো

6

একটি খুব ভাল নিবন্ধ দেখুন " পাইথন ব্যতিক্রমগুলির চূড়ান্ত গাইড "। প্রাথমিক নীতিগুলি হ'ল:

  • সর্বদা (অন্তত) ব্যতিক্রম থেকে উত্তরাধিকারী হন।
  • সর্বদা BaseException.__init__শুধুমাত্র একটি যুক্তি দিয়ে কল করুন ।
  • লাইব্রেরি তৈরি করার সময়, ব্যতিক্রম থেকে উত্তরাধিকার সূত্রে একটি বেস শ্রেণীর সংজ্ঞা দিন।
  • ত্রুটি সম্পর্কে বিশদ সরবরাহ করুন।
  • বিল্টিন ব্যতিক্রমগুলি থেকে উত্তরাধিকারী যখন এটি বোধগম্য হয়।

সংগঠিতকরণ (মডিউলগুলিতে) এবং মোড়ানো ব্যতিক্রম সম্পর্কিত তথ্যও রয়েছে, আমি গাইডটি পড়ার পরামর্শ দিই।


1
এটি কেন SO এ আমি সাধারণত সর্বাধিক উত্সাহিত উত্তর যাচাই করি তার একটি উত্তম উদাহরণ, তবে সাম্প্রতিকতম উত্তরগুলিও। ব্যবহারযোগ্য পুরো সংযোজন, ধন্যবাদ।
যুক্তি অনবস্ট্রাকশন

1
Always call BaseException.__init__ with only one argument.এটি অপ্রয়োজনীয় সীমাবদ্ধতার মতো মনে হচ্ছে, যেহেতু এটি আসলে কোনও সংখ্যক যুক্তি গ্রহণ করে ।
ইউজিন ইয়ারমশ

@ ইউজিনইয়ারম্যাশ আমি সম্মত, এখন আমি তা বুঝতে পারি না। আমি যাইহোক এটি ব্যবহার করি না। হয়তো আমার নিবন্ধটি পুনরায় পড়া উচিত এবং আমার উত্তরটি প্রসারিত করা উচিত।
ইয়ারোস্লাভ নিকিতেনকো

@ ইউজিনিয়ারম্যাশ আমি আর্টিকেলটি আবার পড়েছি। এটি উল্লেখ করা হয়েছে যে বেশ কয়েকটি যুক্তির ক্ষেত্রে সি প্রয়োগকারী "পিওবজেক্ট_সটিআরটি (স্ব-> আরগস) রিটার্ন দেয়;" এর অর্থ একটি স্ট্রিংয়ের বেশ কয়েকটিগুলির চেয়ে ভাল কাজ করা উচিত। তুমি কি তা পরীক্ষা করেছ?
ইয়ারোস্লাভ নিকিতেনকো

3

এই উদাহরণ চেষ্টা করুন

class InvalidInputError(Exception):
    def __init__(self, msg):
        self.msg = msg
    def __str__(self):
        return repr(self.msg)

inp = int(input("Enter a number between 1 to 10:"))
try:
    if type(inp) != int or inp not in list(range(1,11)):
        raise InvalidInputError
except InvalidInputError:
    print("Invalid input entered")

1

আপনার নিজের ব্যতিক্রমগুলি সঠিকভাবে সংজ্ঞায়িত করতে কয়েকটি সেরা অনুশীলন রয়েছে যা আপনাকে অনুসরণ করতে হবে:

  • উত্তরাধিকার সূত্রে প্রাপ্ত একটি বেস শ্রেণীর সংজ্ঞা দাও Exception। এটি প্রকল্পের সাথে সম্পর্কিত যে কোনও ব্যতিক্রম ধরতে অনুমতি দেবে (আরও নির্দিষ্ট ব্যতিক্রমগুলি এর থেকে উত্তরাধিকারী হওয়া উচিত):

    class MyProjectError(Exception):
        """A base class for MyProject exceptions."""

    এই ব্যতিক্রম ক্লাসগুলি একটি পৃথক মডিউল (যেমন exceptions.py) এ সংগঠিত করা সাধারণত একটি ভাল ধারণা।

  • আপনার ব্যতিক্রম অতিরিক্ত তর্ক (গুলি) পাস করার জন্য, __init__()একটি চলক সংখ্যক আর্গুমেন্টের সাথে একটি কাস্টম পদ্ধতি নির্ধারণ করুন । বেস শ্রেণীর যে __init__()কোনও অবস্থানগত আর্গুমেন্টকে পাস করার জন্য এটি কল করুন (মনে রাখবেন BaseException/Exception যে কোনও অবস্থানিক আর্গুমেন্টের প্রত্যাশা করুন ):

    class CustomError(MyProjectError):
        def __init__(self, *args, **kwargs):
            super(CustomError, self).__init__(*args)
            self.foo = kwargs.get('foo')

    অতিরিক্ত যুক্তি দিয়ে এ জাতীয় ব্যতিক্রম বাড়াতে আপনি ব্যবহার করতে পারেন:

    raise CustomError('Something bad happened', foo='foo')

    এই নকশা আসলে মেনে চলে করতে Liskov প্রতিকল্পন নীতি , যেহেতু আপনি একটি উদ্ভূত ব্যতিক্রম ক্লাসের একটা নিদর্শন সঙ্গে একটি বেস ব্যতিক্রম ক্লাসের একটা নিদর্শন প্রতিস্থাপন করতে পারেন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.