নেস্টেড ট্রাই / ব্লক ব্যতীত কীভাবে ব্যতিক্রম পুনরায় উত্থাপন করবেন?


112

আমি জানি যে আমি যদি কোনও ব্যতিক্রম পুনরায় উত্থাপন করতে চাই তবে আমি raiseস্বতন্ত্র exceptব্লকে যুক্তি ছাড়াই সহজ ব্যবহার করি । কিন্তু একটি নেস্টেড মত প্রকাশ দেওয়া

try:
    something()
except SomeError as e:
    try:
        plan_B()
    except AlsoFailsError:
        raise e  # I'd like to raise the SomeError as if plan_B()
                 # didn't raise the AlsoFailsError

SomeErrorস্ট্যাকের ট্রেস না ভেঙে আমি কীভাবে পুনরায় বাড়াতে পারি ? raiseএকা এই ক্ষেত্রে আরও সাম্প্রতিকতম পুনরায় উত্থাপন করবে AlsoFailsError। বা এই সমস্যাটি এড়াতে আমি কীভাবে আমার কোডটি রিফ্যাক্টর করতে পারি?


4
আপনি কি plan_Bঅন্য কোনও কার্য সম্পাদনের চেষ্টা করেছেন যা Trueসাফল্য এবং Falseব্যতিক্রমের ক্ষেত্রে ফিরে আসে ? তারপরে বাইরের exceptব্লকটি কেবল হতে পারেif not try_plan_B(): raise
ড্রু ম্যাকগোয়েন

@ ড্র্রুম্যাকউইন দুর্ভাগ্যক্রমে আরও বাস্তব ঘটনাটি হ'ল এটি একটি ফাংশনের মধ্যে যথেচ্ছ বিষয়গুলি গ্রহণ করে argএবং আমি কল করার চেষ্টা করতাম arg.plan_B()যা কোনও পরিকল্পনা বি প্রদান না AttributeErrorকরার কারণে উত্থাপিত হতে পারেarg
টোবিয়াস কেইঞ্জলার

ট্রেসব্যাক মডিউলটি দেখুন: docs.python.org/2/library/traceback.html#traceback- উদাহরণ
পাকো

@ পাকো ধন্যবাদ, আমি করব (যদিও উত্তর ইতিমধ্যে একটি সহজ উপায় দেখায়)
টোবিয়াস কেইনজলার

@DrewMcGowen আমি লিখেছিলেন আপনার মন্তব্যকে উপর ভিত্তি করে একটি উত্তর , যা কম pythonic দেখায় user4815162342 এর উত্তর যদিও। তবে এটি আমার ফেরতের মূল্যও অর্জন করা এবং plan_Bব্যতিক্রম বাড়ানোর অনুমতি দেওয়ার কারণে
টোবিয়াস কেইনজলার

উত্তর:


133

পাইথন 3 হিসাবে ট্রেসব্যাকটি ব্যাতিক্রিয়ায় সংরক্ষণ করা হয়, সুতরাং একটি সাধারণ raise e(বেশিরভাগ ক্ষেত্রে) সঠিক জিনিসটি করবে:

try:
    something()
except SomeError as e:
    try:
        plan_B()
    except AlsoFailsError:
        raise e  # or raise e from None - see below

ট্রেসব্যাক উত্পাদিত একটি অতিরিক্ত যে বিজ্ঞপ্তি অন্তর্ভুক্ত করা হবে SomeErrorযখন হ্যান্ডলিং ঘটেছে AlsoFailsError(কারণ raise eভিতরে হচ্ছে except AlsoFailsError)। এটি বিভ্রান্তিকর কারণ বাস্তবে যা ঘটেছিল তা অন্যদিকে - আমরা AlsoFailsErrorপুনরুদ্ধার করার চেষ্টা করার সময় এটির মুখোমুখি হয়েছি এবং পরিচালনা করেছি SomeError। একটি ট্রেসব্যাক যে অন্তর্ভুক্ত নয় প্রাপ্ত AlsoFailsError, প্রতিস্থাপন raise eসঙ্গে raise e from None

পাইথন 2 এ আপনি ব্যতিক্রমের ধরণ, মান এবং স্থানীয় ভেরিয়েবলগুলিতে ট্রেসব্যাক সংরক্ষণ করতে পারেন এবং ত্রি-যুক্তি রূপটিraise ব্যবহার করতে পারেন :

try:
    something()
except SomeError:
    t, v, tb = sys.exc_info()
    try:
        plan_B()
    except AlsoFailsError:
        raise t, v, tb

নিখুঁত, আমি এটি এখানে পেয়েছি যা , ধন্যবাদ! যদিও পরামর্শটি raise self.exc_info[1], None, self.exc_info[2]পরে রয়েছে self.exc_info = sys.exc_info()- [1]কোনও কারণে প্রথমে অবস্থান
টোবিয়াস কেইনজলার

4
@ তোবিয়াস কিইনজেলার raise t, None, tbব্যতিক্রমের মান হারাবে এবং raiseএটিকে টাইপ থেকে পুনরায় ইনস্ট্যান্ট করতে বাধ্য করবে , আপনাকে একটি কম নির্দিষ্ট (বা কেবল ভুল) ব্যতিক্রমের মান প্রদান করবে giving উদাহরণস্বরূপ, যদি উত্থাপিত ব্যতিক্রম হয় KeyError("some-key"), এটি কেবল পুনরায় উত্থাপন করবে KeyError()এবং সঠিক ট্র্যাকব্যাক থেকে অনুপস্থিত কীটি বাদ দেবে।
ব্যবহারকারী 4815162342

4
@ তোবিয়াস কিইনজলার এখনও পাইথন 3 তে তা প্রকাশ করা সম্ভব হবে raise v.with_traceback(tb)। (আপনার মন্তব্য এমনকি আরও বেশি কিছু বলে, এটি মানটিকে পুনরায় ইনস্ট্যান্ট করার প্রস্তাব ব্যতীত))
ব্যবহারকারী 481515162342

4
এছাড়াও, sys.exc_info()পাইথন ২.০ (১৩ বছর আগে মুক্তি পেয়েছিল) এর আগে স্থানীয় ভেরিয়েবলে সংরক্ষণ না করার লাল সতর্কতাটি আজকের দিনে হাস্যকর rid আধুনিক পাইথনটি চক্র সংগ্রাহক ছাড়াই অদূরে অকেজো হয়ে উঠবে, কারণ প্রতিটি অ-তুচ্ছ পাইথন লাইব্রেরি বিরতি ছাড়াই চক্র তৈরি করে এবং তাদের সঠিক পরিষ্কারের উপর নির্ভর করে।
ব্যবহারকারী 4815162342

4
@ ব্যবহারকারী 4815162342 আপনি "অন্য কোনও ত্রুটি ঘটেছে" নেস্টেড ত্রুটি "উত্স ই থেকে নয়" লিখে লিখে হত্যা করতে পারেন।
ম্যাথিয়াস উরলিচস

19

এমনকি যদি গৃহীত সমাধানটি সঠিক হয় তবে সিক্স লাইব্রেরিটির দিকে লক্ষ্য করা ভাল যা ব্যবহার করে পাইথন 2 + 3 সমাধান রয়েছে six.reraise

ছয় পুনরায় পুনরুদ্ধার করুন ( exc_type , exc_value , exc_traceback = কিছুই নেই)

সম্ভবত একটি আলাদা ট্রেসব্যাক দিয়ে একটি ব্যতিক্রম পুনরায় করুন। [...]

সুতরাং, আপনি লিখতে পারেন:

import six


try:
    something()
except SomeError:
    t, v, tb = sys.exc_info()
    try:
        plan_B()
    except AlsoFailsError:
        six.reraise(t, v, tb)

4
ভাল পয়েন্ট - সিক্সের কথা বলা আপনি six.raise_fromযদি ব্যবহার করে এমন তথ্যও অন্তর্ভুক্ত করতে চান তবে আপনি এটিও ব্যবহার করতে পারেন plan_B()
টোবিয়াস কেইনজলার

4
@ টোবিয়াস কেইনজলার: আমি মনে করি এটি একটি আলাদা ব্যবহার: six.raise_fromআপনার একটি নতুন ব্যতিক্রম তৈরি হয়েছে যা পূর্বেরটির সাথে যুক্ত রয়েছে, আপনি পুনরায় উত্থাপন করবেন না , সুতরাং ট্রেস ব্যাকটি আলাদা।
লরেন্ট LAPORTE

4
আমার বক্তব্যটি হ'ল - যদি আপনি reraiseএই ধারণাটি কেবল something()ছুঁড়ে ফেলে দেন SomeErrorতবে আপনি raise_fromযদি জানতেও পারেন যে plan_B()এটি কার্যকর হয়েছে তবে ছোঁড়াচ্ছেন AlsoFailsError। সুতরাং এটি ব্যবহারের উপর নির্ভর করে। আমি মনে করি raise_fromডিবাগ করা সহজ করে দেবে
টোবিয়াস কেইনজলার

9

অনুযায়ী ড্রিউ McGowen এর পরামর্শ , কিন্তু একটি সাধারণ ক্ষেত্রে (যেখানে একটি ফিরতি মূল্য তদারক sউপস্থিত), এখানে বিকল্প নেই user4815162342 এর উত্তর :

try:
    s = something()
except SomeError as e:
    def wrapped_plan_B():
        try:
            return False, plan_B()
        except:
            return True, None
    failed, s = wrapped_plan_B()
    if failed:
        raise

4
এই পদ্ধতির সুন্দর জিনিসটি এটি পাইথন 2 এবং 3 এ অপরিবর্তিত কাজ করে
ব্যবহারকারী 481515162342

4
@ ব্যবহারকারী 4815162342 ভাল পয়েন্ট :) পাইথন 3 এর মধ্যে আমি বিবেচনা করেছি raise from, সুতরাং স্ট্যাক ট্রেস আমাকে বি বিতে ব্যর্থ হতে দেবে। যা পাইথন 2 এ অনুকরণ করা যায়
টোবিয়াস কেইনজলার

5

পাইথন ৩.৫+ ত্রুটিযুক্তভাবে ট্র্যাসব্যাক তথ্য সংযুক্ত করে, তাই এটি আলাদাভাবে সংরক্ষণ করার দরকার নেই।

>>> def f():
...   try:
...     raise SyntaxError
...   except Exception as e:
...     err = e
...     try:
...       raise AttributeError
...     except Exception as e1:
...       raise err from None
>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 9, in f
  File "<stdin>", line 3, in f
SyntaxError: None
>>> 

4
প্রশ্নটি চলাকালীন সময়ে ঘটে যাওয়া আরেকটি ব্যতিক্রম সম্পর্কে except। তবে আপনি ঠিক বলেছেন, আমি যখন প্রতিস্থাপন করব তখন err = eবলুন raise AttributeError, আপনি প্রথমে SyntaxErrorস্ট্যাক ট্রেস পাবেন, তার পরে একটি During handling of the above exception, another exception occurred:এবং AttributeErrorস্ট্যাক ট্রেস পাবেন। জেনে রাখা ভাল, যদিও দুর্ভাগ্যক্রমে কেউ ইনস্টল হওয়া 3.5+ এর উপর নির্ভর করতে পারে না। PS: ff verstehen nicht-Deutsche vermutlich nicht;)
টোবিয়াস কেইনজলার

ঠিক আছে, সুতরাং আমি অন্য একটি ব্যতিক্রম উত্থাপনের জন্য উদাহরণটি পরিবর্তন করেছি, যা আমি প্রথমটিকে পুনরায় উত্থাপিত করার সময় (মূল প্রশ্ন হিসাবে জিজ্ঞাসা করা) উপেক্ষা করে যায় ignored
ম্যাথিয়াস উরলিচস

4
@ তোবিয়াস কিইনজেলার 3.5+ (যা আমি এটিতে পরিবর্তন করেছি) এটি বিশ্বব্যাপী স্বীকৃত ফর্ম্যাট বলে মনে হচ্ছে। ডেঙ্কস্ট ডু ছিল? ;)
লিনাসগ

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