একটি ব্যতিক্রম বস্তু থেকে ট্রেসব্যাক তথ্য বের করুন


111

একটি ব্যতিক্রম বস্তু দেওয়া (অজানা উত্সের) এর ট্রেসব্যাক পাওয়ার কোনও উপায় আছে? আমার এই কোড আছে:

def stuff():
   try:
       .....
       return useful
   except Exception as e:
       return e

result = stuff()
if isinstance(result, Exception):
    result.traceback <-- How?

আমি একবারে ব্যতিক্রম অবজেক্টটি পেয়ে গেলে কীভাবে এটি সন্ধান করতে পারি?

উত্তর:


92

এই প্রশ্নের উত্তরটি আপনি ব্যবহার করছেন পাইথনের সংস্করণে depends

পাইথন 3 এ

এটি সহজ: ব্যতিক্রমগুলি এমন কোনও __traceback__বৈশিষ্ট্যে সজ্জিত হয় যা ট্রেসব্যাক ধারণ করে। এই বৈশিষ্ট্যটিও লিখনযোগ্য, এবং with_tracebackব্যতিক্রম পদ্ধতিটি ব্যবহার করে সুবিধামত সেট করা যেতে পারে :

raise Exception("foo occurred").with_traceback(tracebackobj)

এই বৈশিষ্ট্যগুলি raiseনথির অংশ হিসাবে ন্যূনতমভাবে বর্ণিত হয়েছে ।

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

পাইথন 2 এ

এটা বিরক্তিকর জটিল। ট্রেসব্যাকগুলির সাথে সমস্যাটি হ'ল তাদের স্ট্যাক ফ্রেমের সাথে উল্লেখ রয়েছে এবং স্ট্যাক ফ্রেমে ট্র্যাকব্যাকগুলির সাথে রেফারেন্স রয়েছে যা স্ট্যাক ফ্রেমের সাথে উল্লেখ রয়েছে ... আপনার ধারণা পাওয়া যায় get এটি আবর্জনা সংগ্রহকারীদের জন্য সমস্যা সৃষ্টি করে। ( প্রথমে এটি দেখানোর জন্য ইক্যামচারকে ধন্যবাদ ।)

এটি সমাধানের দুর্দান্ত উপায় হ'ল অধ্যায়টি ছাড়ার পরে সার্জিকভাবে চক্রটি ভেঙে দেওয়াexcept , এটি পাইথন 3 যা করে। পাইথন 2 সলিউশনটি অনেক কৃপণকর: আপনাকে একটি অ্যাড-হক ফাংশন সরবরাহ করা হবে sys.exc_info(), যা কেবল except ক্লজের অভ্যন্তরে কাজ করে । এটি ব্যতিক্রম, ব্যতিক্রমের ধরন এবং বর্তমানে যে কোনও ব্যতিক্রম বর্তমানে পরিচালনা করা হচ্ছে তার জন্য ট্রেসব্যাক সমন্বিত একটি টুপল ফেরত দেয়।

সুতরাং আপনি যদি exceptক্লজের অভ্যন্তরে থাকেন sys.exc_info()তবে tracebackমডিউলটির পাশাপাশি আউটপুটটি বিভিন্ন দরকারী জিনিসগুলি ব্যবহার করতে পারেন :

>>> import sys, traceback
>>> def raise_exception():
...     try:
...         raise Exception
...     except Exception:
...         ex_type, ex, tb = sys.exc_info()
...         traceback.print_tb(tb)
...     finally:
...         del tb
... 
>>> raise_exception()
  File "<stdin>", line 3, in raise_exception

তবে আপনার সম্পাদনাটি ইঙ্গিত দিচ্ছে, আপনি ইতিমধ্যে হ্যান্ডেল করার পরেও যদি আপনার ব্যতিক্রমটি পরিচালনা না করা হত তবে ট্রেসব্যাকটি মুদ্রিত হওয়ার চেষ্টা করছেন। এটি অনেক কঠিন প্রশ্ন। দুর্ভাগ্যক্রমে, কোনও ব্যতিক্রম হ্যান্ডেল না করা অবস্থায় ফিরে আসে । অন্যান্য সম্পর্কিত বৈশিষ্ট্যগুলিও সাহায্য করে না। কোনও ব্যতিক্রম পরিচালনা করা হচ্ছে না যখন অবচয় এবং অপরিজ্ঞাত; নিখুঁত বলে মনে হচ্ছে তবে এটি কেবল ইন্টারেক্টিভ সেশনের সময় সংজ্ঞায়িত হবে বলে মনে হয়।sys.exc_info(None, None, None)syssys.exc_tracebacksys.last_traceback

যদি আপনি কীভাবে ব্যতিক্রমটি উত্থাপিত হয় তা নিয়ন্ত্রণ করতে পারেন তবে আপনি কিছু তথ্য সঞ্চয় করতে ব্যবহার করতে পারবেন inspectএবং একটি কাস্টম ব্যতিক্রম । তবে আমি কীভাবে এটি কাজ করবে তা পুরোপুরি নিশ্চিত নই।

সত্য কথা বলতে, একটি ব্যতিক্রম ধরা এবং ফিরিয়ে দেওয়া এক ধরণের অস্বাভাবিক কাজ। এটি কোনও চিহ্ন হতে পারে যা আপনাকে যাইহোক রিফ্যাক্টর করতে হবে।


আমি সম্মত হই যে ব্যতিক্রমগুলি ফিরিয়ে নেওয়া কোনওভাবেই প্রচলিত নয়, এর পিছনে কিছু যুক্তি দেখানোর জন্য আমার অন্য প্রশ্নটি দেখুন ।
জর্জি

@ thg435, ঠিক আছে, এটি তখন আরও অর্থবোধ করে। আমি আপনার অন্যান্য প্রশ্নের পরামর্শ দিচ্ছি কলব্যাক পদ্ধতিরsys.exc_info সাথে একযোগে ব্যবহার করে আমার উপরের সমাধানটি বিবেচনা করুন ।
প্রেরক

ট্রেসব্যাক অবজেক্টগুলিতে আরও তথ্য (খুব অল্প) আছে: ডকস.পিথথন.আর / ৩ / লাইব্রেরি
টাইপস.ইচটিএমএল

69

যেহেতু পাইথন 3.0 [PEP 3109] ক্লাসে নির্মিত Exceptionটি __traceback__অ্যাট্রিবিউট যা ধারণ করে traceback object(পাইথন 3.2.3 সহ):

>>> try:
...     raise Exception()
... except Exception as e:
...     tb = e.__traceback__
...
>>> tb
<traceback object at 0x00000000022A9208>

সমস্যাটি হ'ল কিছুক্ষণ গুগলিংয়ের__traceback__ পরে আমি কেবল কয়েকটি নিবন্ধ পেয়েছি কিন্তু এর মধ্যে কোনওটিই আপনাকে ব্যবহার করা উচিত বা হবে না তা বর্ণনা করে না __traceback__

তবে পাইথন 3 ডকুমেন্টেশনের জন্যraise বলেছেন যে:

একটি ট্রেসব্যাক অবজেক্ট সাধারণত স্বয়ংক্রিয়ভাবে তৈরি হয় যখন একটি ব্যতিক্রম উত্থাপিত হয় এবং __traceback__বৈশিষ্ট্য হিসাবে এটি সংযুক্ত করা হয় , যা লিখনযোগ্য।

সুতরাং আমি ধরে নিই যে এটি ব্যবহার করা উচিত।


4
হ্যাঁ, এটি ব্যবহার করা বোঝায়। পাইথন 3.0-এ নতুন কী থেকে "" পিইপি 3134: ব্যতিক্রমী অবজেক্টসগুলি এখন তাদের ট্রেসব্যাকটিকে ট্রেসব্যাক বৈশিষ্ট্য হিসাবে সংরক্ষণ করে This যদিও পরবর্তীটি সরানো হয়নি) "।
ম্যাকিয়েজ স্জপাকোভস্কি

আমি উত্তর বুঝতে পারি না কেন এই উত্তরটি এত দ্বিধাদ্বন্দ্বপূর্ণ এবং দ্বিখণ্ডিত। এটি একটি নথিভুক্ত সম্পত্তি; কেন এটি "ব্যবহারের বোঝায়" হবে না ?
মার্ক আমেরিকা

2
@ মার্ক অ্যামেরি সম্ভবত নামটিতে __ইঙ্গিত দেয় যে এটি বাস্তবায়নের বিবরণ, কোনও পাবলিক সম্পত্তি নয়?
বেসিক

4
@ বেসিক এটি এখানে এটি নির্দেশ করে না। প্রচলিতভাবে পাইথনে __fooএকটি ব্যক্তিগত পদ্ধতি তবে __foo__(পিছনে আন্ডারস্কোরগুলিও খুব বেশি) একটি "যাদু" পদ্ধতি (এবং ব্যক্তিগত নয়)।
মার্ক অ্যামেরি

1
এফওয়াইআই, __traceback__বৈশিষ্ট্যটি আপনার পছন্দ মত 100% সুরক্ষিত, কোনও জিসি এর সাথে জড়িত নয়। ডকুমেন্টেশন থেকে এটি বলা শক্ত, তবে ইকাম্তর এর শক্ত প্রমাণ খুঁজে পেয়েছে
প্রেরক

38

পাইথন 3 এ ব্যতিক্রমী অবজেক্ট থেকে স্ট্রিং হিসাবে ট্রেসব্যাক পাওয়ার উপায়:

import traceback

# `e` is an exception object that you get from somewhere
traceback_str = ''.join(traceback.format_tb(e.__traceback__))

traceback.format_tb(...)স্ট্রিংগুলির একটি তালিকা প্রদান করে। ''.join(...)তাদের একসাথে যোগদান। আরও রেফারেন্সের জন্য, দয়া করে এখানে যান: https://docs.python.org/3/library/traceback.html#traceback.format_tb


21

অন্যদিকে, যদি আপনি এটি আপনার টার্মিনালে মুদ্রিত দেখতে দেখতে পুরো ট্রাসব্যাক পেতে চান তবে আপনি এটি চান:

>>> try:
...     print(1/0)
... except Exception as e:
...     exc = e
...
>>> exc
ZeroDivisionError('division by zero')
>>> tb_str = traceback.format_exception(etype=type(exc), value=exc, tb=exc.__traceback__)
>>> tb_str
['Traceback (most recent call last):\n', '  File "<stdin>", line 2, in <module>\n', 'ZeroDivisionError: division by zero\n']
>>> print("".join(tb_str))
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: division by zero

যদি আপনি format_tbউপরের উত্তরগুলি ব্যবহার করেন তবে আপনি কম তথ্য পাবেন:

>>> tb_str = "".join(traceback.format_tb(exc.__traceback__))
>>> print("".join(tb_str))
  File "<stdin>", line 2, in <module>

4
অবশেষে! এটি শীর্ষ উত্তর হওয়া উচিত। আপনাকে ধন্যবাদ, ড্যানিয়েল!
ড্যানি

3
আরেগ, আমি এটি খুঁজে পাওয়ার আগে আমি এটি নির্ধারণের জন্য শেষ 20 মিনিট সময় কাটিয়েছি :-) etype=type(exc)এখন বাদ দেওয়া যেতে পারে বিটিডব্লিউ: "সংস্করণ 3.5 in-তে পরিবর্তিত হয়েছে: টাইপ যুক্তি উপেক্ষা করা হয় এবং মানের ধরণ থেকে অনুমান করা হয়।" docs.python.org/3.7/library/… পাইথনে পরীক্ষিত 3.7.3।
সিরো সান্তিলি 郝海东 冠状 病 六四 事件

8

ব্যাতিক্রমণে ট্রেসব্যাক সংরক্ষণ না করার খুব ভাল কারণ রয়েছে; যেহেতু ট্রেসব্যাকটি তার স্ট্যাকের স্থানীয়দের রেফারেন্স ধারণ করে, এর ফলে একটি বিজ্ঞপ্তি রেফারেন্স এবং (অস্থায়ী) মেমরি ফাঁস হয়ে যাবে যতক্ষণ না বিজ্ঞপ্তি জিসি লিক না করে। (এই কারণেই আপনি কখনই কোনও স্থানীয় ভেরিয়েবলে ট্রেসব্যাক সংরক্ষণ করবেন না ।)

আমি যে বিষয়টি কেবলমাত্র ভাবতে পারি সে সম্পর্কে আপনার জন্য বানরপ্যাচের গ্লোবালগুলি stuffহ'ল এটি যখন মনে করে যে Exceptionএটি আসলে এটি একটি বিশেষ ধরণের ধরছে এবং ব্যতিক্রমটি আপনাকে কলার হিসাবে প্রচার করে:

module_containing_stuff.Exception = type("BogusException", (Exception,), {})
try:
    stuff()
except Exception:
    import sys
    print sys.exc_info()

7
এটা ভুল. পাইথন 3 ব্যতিক্রমগুলিতে ট্রেসব্যাক অবজেক্টটি রাখে e.__traceback__
গ্লেন মেইনার্ড

6
@ গ্লেনমায়নার্ড পাইথন 3 পিইপি 3110except অনুযায়ী ব্লকটি থেকে বেরিয়ে আসার ব্যতিক্রম লক্ষ্য মুছে ফেলার মাধ্যমে সমস্যার সমাধান করে ।
ইকামত্মুর
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.