ব্যতিক্রম বর্ণনা এবং স্ট্যাক ট্রেস পান যা একটি স্ট্রিং হিসাবে ব্যতিক্রম ঘটায়


423

পাইথনে স্ট্যাক ট্রেস এবং ব্যতিক্রম সম্পর্কে আমি প্রচুর পোস্ট দেখেছি। তবে আমার যা প্রয়োজন তা খুঁজে পাইনি।

আমার কাছে পাইথন ২.7 কোড রয়েছে যা একটি ব্যতিক্রম বাড়াতে পারে। আমি এটি ধরতে চাই এবং স্ট্রিংটির সম্পূর্ণ বিবরণ এবং স্ট্যাক ট্রেসকে ত্রুটির কারণ হিসাবে চিহ্নিত করতে চাই (কেবলমাত্র আমরা কনসোলটিতে দেখতে ব্যবহার করি)। জিইআইআই-এর একটি পাঠ্য বাক্সে এটি মুদ্রণের জন্য আমার এই স্ট্রিংটি দরকার।

এটার মতো কিছু:

try:
    method_that_can_raise_an_exception(params)
except Exception as e:
    print_to_textbox(complete_exception_description(e))

সমস্যাটি হচ্ছে: ফাংশনটি complete_exception_descriptionকী?

উত্তর:


615

tracebackমডিউলটি দেখুন , বিশেষত format_exc()ফাংশন। এখানে

import traceback

try:
    raise ValueError
except ValueError:
    tb = traceback.format_exc()
else:
    tb = "No error"
finally:
    print tb

2
এটি কি সর্বশেষ ত্রুটি নিয়ে কাজ করে? আপনি যদি কোডের অন্যান্য বিটগুলিতে ত্রুটিটি পাস করতে শুরু করেন তবে কি হবে? আমি একটি log_error(err)ফাংশন লিখছি ।
আনানফায়

এটি ধরা পড়ে এবং পরিচালনা করা ত্রুটি নিয়ে কাজ করে।
kindall

74

আসুন আমরা পুরো স্ট্যাকট্রেস পেয়েছি তা প্রদর্শনের জন্য একটি শালীন জটিল স্ট্যাকট্রেস তৈরি করি:

def raise_error():
    raise RuntimeError('something bad happened!')

def do_something_that_might_error():
    raise_error()

সম্পূর্ণ স্ট্যাকট্রেস লগইন হচ্ছে

আপনার মডিউলটির জন্য একটি লগার স্থাপন করা সর্বোত্তম অনুশীলন। এটি মডিউলটির নাম জানবে এবং স্তরগুলি পরিবর্তন করতে সক্ষম হবে (অন্যান্য বৈশিষ্ট্যগুলির মধ্যে যেমন হ্যান্ডলারের)

import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

এবং ত্রুটি পেতে আমরা এই লগারটি ব্যবহার করতে পারি:

try:
    do_something_that_might_error()
except Exception as error:
    logger.exception(error)

কোন লগ:

ERROR:__main__:something bad happened!
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

এবং তাই আমরা যখন আমাদের একটি ত্রুটি ঘটে তখন একই আউটপুট পাই:

>>> do_something_that_might_error()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

কেবল স্ট্রিং পাচ্ছে

আপনি যদি সত্যিই কেবল স্ট্রিং চান, তবে traceback.format_excপরিবর্তে ফাংশনটি ব্যবহার করুন, এখানে স্ট্রিংটিতে লগিং প্রদর্শন করুন:

import traceback
try:
    do_something_that_might_error()
except Exception as error:
    just_the_string = traceback.format_exc()
    logger.debug(just_the_string)

কোন লগ:

DEBUG:__main__:Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

1
পাইথন 3 ব্যবহার করার সময় এটিই কি সেরা পদ্ধতি (উদাহরণস্বরূপ নীচের কয়েকটি উত্তরের তুলনায়)?
ইয়ুন্তি

1
@ ইউন্টি আমি বিশ্বাস করি এই পিআইপিটি পাইথন 2 এবং 3 জুড়ে সামঞ্জস্যপূর্ণ হয়েছে
অ্যারন হল

এই উত্তরের ফর্ম্যাটিংটি মেটাতে আলোচনা করা হয়েছিল: meta.stackoverflow.com/questions/386477/…
লন্ডিন

আমি নিম্নলিখিতটিতে একটি সম্পাদনা পাঠিয়েছি তবে লগইন করা হয়নি যাতে নামহীন হিসাবে দেখানো হয়েছে:except Exception as e: logger.exception("<<clearly and distinctly describe what failed here>>", exc_info=e)
আর্টজ

@ আরএনটিজি আমি আপনাকে কৃতজ্ঞ যে আপনি সাহায্য করার চেষ্টা করছেন, তবে সেই সম্পাদনাটি ক্ষতিকারক পরিবর্তন হবে। আপনি যে API গুলি ব্যবহারের চেষ্টা করছেন তা পুরোপুরি বুঝতে দয়া করে ভবিষ্যতে আরও বেশি সতর্ক হন। এই ক্ষেত্রে, exc_infoআর্গুমেন্টটি "ব্যতিক্রম টুপল" প্রত্যাশা করে যখন errorএটি Exceptionবস্তুর (বা সাবক্লাস) উদাহরণস্বরূপ , এবং এতে কোনও পরিবর্তন errorকরার দরকার নেই e
অ্যারন হল

39

পাইথন 3 এর সাথে, নিম্নলিখিত কোডগুলি কোনও Exceptionঅবজেক্টটি বিন্যাস করবে ঠিক যেমন ব্যবহার করে প্রাপ্ত হবে traceback.format_exc():

import traceback

try: 
    method_that_can_raise_an_exception(params)
except Exception as ex:
    print(''.join(traceback.format_exception(etype=type(ex), value=ex, tb=ex.__traceback__)))

সুবিধাটি হ'ল যে কেবলমাত্র Exceptionঅবজেক্টটি প্রয়োজন (রেকর্ডকৃত __traceback__বৈশিষ্ট্যের জন্য ধন্যবাদ ), এবং আরও প্রসেসিংয়ের জন্য অন্য কোনও কার্যক্রমে যুক্তি হিসাবে আরও সহজেই পাস করা যেতে পারে।


1
এটি sys.exc_info () এর চেয়ে ভাল যা ওও স্টাইলের পক্ষে ভাল নয় এবং এটি বৈশ্বিক পরিবর্তনশীল ব্যবহার করে।
ওয়েইচিং 林 煒

এই বিশেষভাবে অনুরোধ কিভাবে ব্যতিক্রম বস্তু থেকে ট্রেসব্যাক পেতে হিসাবে আপনি এখানে কাজ করেছেন stackoverflow.com/questions/11414894/...
সিরো Santilli郝海东冠状病六四事件法轮功

সেখানে ব্যবহার না করেই একটি সহজ Python3 উপায় .__traceback__এবং typeদেখুন stackoverflow.com/a/58764987/5717886
don_vanchos

34
>>> import sys
>>> import traceback
>>> try:
...   5 / 0
... except ZeroDivisionError as e:
...   type_, value_, traceback_ = sys.exc_info()
>>> traceback.format_tb(traceback_)
['  File "<stdin>", line 2, in <module>\n']
>>> value_
ZeroDivisionError('integer division or modulo by zero',)
>>> type_
<type 'exceptions.ZeroDivisionError'>
>>>
>>> 5 / 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero

আপনি মডিউলটির ফর্ম্যাট করতে তথ্য এবং ফাংশন সংগ্রহ করতে sys.exc_info () ব্যবহার করেন traceback। এটির ফর্ম্যাট করার জন্য এখানে কয়েকটি উদাহরণ।

সম্পূর্ণ ব্যতিক্রম স্ট্রিংটি এখানে:

>>> ex = traceback.format_exception(type_, value_, traceback_)
>>> ex
['Traceback (most recent call last):\n', '  File "<stdin>", line 2, in <module>\n', 'ZeroDivisionError: integer division or modulo by zero\n']

9

ঐ ব্যবহারের জন্য পাইথন -3

tracebackমডিউল ব্যবহার করে এবং exception.__traceback__নিম্নলিখিতরূপে স্ট্যাক-ট্রেস বের করা যায়:

  • ব্যবহার করে বর্তমান স্ট্যাক-ট্রেস ধরুনtraceback.extract_stack()
  • শেষ তিনটি উপাদান মুছুন (সেগুলি স্ট্যাকের মধ্যে যেমন আমার ডিবাগ ফাংশনে প্রবেশ করেছে)
  • যোগ __traceback__ব্যতিক্রম বস্তু থেকে ব্যবহারtraceback.extract_tb()
  • ব্যবহার করে পুরো জিনিস ফর্ম্যাট করুন traceback.format_list()
import traceback
def exception_to_string(excp):
   stack = traceback.extract_stack()[:-3] + traceback.extract_tb(excp.__traceback__)  # add limit=?? 
   pretty = traceback.format_list(stack)
   return ''.join(pretty) + '\n  {} {}'.format(excp.__class__,excp)

একটি সহজ বিক্ষোভ:

def foo():
    try:
        something_invalid()
    except Exception as e:
        print(exception_to_string(e))

def bar():
    return foo()

আমরা যখন কল করি তখন আমরা নিম্নলিখিত আউটপুটটি পাই bar():

  File "./test.py", line 57, in <module>
    bar()
  File "./test.py", line 55, in bar
    return foo()
  File "./test.py", line 50, in foo
    something_invalid()

  <class 'NameError'> name 'something_invalid' is not defined

এটি দেখতে পঠনযোগ্য জটিল কোডের মতো দেখাচ্ছে। ইন পাইথন 3.5+ আরো একটি মার্জিত এবং সহজ উপায় থাকে: stackoverflow.com/a/58764987/5717886
don_vanchos

6

আপনি স্থানীয় ভেরিয়েবলের মান, উত্স কোডের প্রসঙ্গ, ফাংশন প্যারামিটারগুলি সহ কিছুটা ভাল, সুন্দরভাবে ফর্ম্যাট করা ব্যতিক্রম তথ্য পেতে বিল্ট-ইন পাইথন মডিউল, সিজিবিটি ব্যবহার করেও বিবেচনা করতে পারেন ..

উদাহরণস্বরূপ এই কোডের জন্য ...

import cgitb
cgitb.enable(format='text')

def func2(a, divisor):
    return a / divisor

def func1(a, b):
    c = b - 5
    return func2(a, c)

func1(1, 5)

আমরা এই ব্যতিক্রম আউটপুট পেতে ...

ZeroDivisionError
Python 3.4.2: C:\tools\python\python.exe
Tue Sep 22 15:29:33 2015

A problem occurred in a Python script.  Here is the sequence of
function calls leading up to the error, in the order they occurred.

 c:\TEMP\cgittest2.py in <module>()
    7 def func1(a, b):
    8   c = b - 5
    9   return func2(a, c)
   10
   11 func1(1, 5)
func1 = <function func1>

 c:\TEMP\cgittest2.py in func1(a=1, b=5)
    7 def func1(a, b):
    8   c = b - 5
    9   return func2(a, c)
   10
   11 func1(1, 5)
global func2 = <function func2>
a = 1
c = 0

 c:\TEMP\cgittest2.py in func2(a=1, divisor=0)
    3
    4 def func2(a, divisor):
    5   return a / divisor
    6
    7 def func1(a, b):
a = 1
divisor = 0
ZeroDivisionError: division by zero
    __cause__ = None
    __class__ = <class 'ZeroDivisionError'>
    __context__ = None
    __delattr__ = <method-wrapper '__delattr__' of ZeroDivisionError object>
    __dict__ = {}
    __dir__ = <built-in method __dir__ of ZeroDivisionError object>
    __doc__ = 'Second argument to a division or modulo operation was zero.'
    __eq__ = <method-wrapper '__eq__' of ZeroDivisionError object>
    __format__ = <built-in method __format__ of ZeroDivisionError object>
    __ge__ = <method-wrapper '__ge__' of ZeroDivisionError object>
    __getattribute__ = <method-wrapper '__getattribute__' of ZeroDivisionError object>
    __gt__ = <method-wrapper '__gt__' of ZeroDivisionError object>
    __hash__ = <method-wrapper '__hash__' of ZeroDivisionError object>
    __init__ = <method-wrapper '__init__' of ZeroDivisionError object>
    __le__ = <method-wrapper '__le__' of ZeroDivisionError object>
    __lt__ = <method-wrapper '__lt__' of ZeroDivisionError object>
    __ne__ = <method-wrapper '__ne__' of ZeroDivisionError object>
    __new__ = <built-in method __new__ of type object>
    __reduce__ = <built-in method __reduce__ of ZeroDivisionError object>
    __reduce_ex__ = <built-in method __reduce_ex__ of ZeroDivisionError object>
    __repr__ = <method-wrapper '__repr__' of ZeroDivisionError object>
    __setattr__ = <method-wrapper '__setattr__' of ZeroDivisionError object>
    __setstate__ = <built-in method __setstate__ of ZeroDivisionError object>
    __sizeof__ = <built-in method __sizeof__ of ZeroDivisionError object>
    __str__ = <method-wrapper '__str__' of ZeroDivisionError object>
    __subclasshook__ = <built-in method __subclasshook__ of type object>
    __suppress_context__ = False
    __traceback__ = <traceback object>
    args = ('division by zero',)
    with_traceback = <built-in method with_traceback of ZeroDivisionError object>

The above is a description of an error in a Python program.  Here is
the original traceback:

Traceback (most recent call last):
  File "cgittest2.py", line 11, in <module>
    func1(1, 5)
  File "cgittest2.py", line 9, in func1
    return func2(a, c)
  File "cgittest2.py", line 5, in func2
    return a / divisor
ZeroDivisionError: division by zero

5

আপনি যদি কোনও ব্যতিক্রম পরিচালনা না করা হয় তখন একই তথ্য দেওয়াতে চাইলে আপনি এই জাতীয় কিছু করতে পারেন। কি import tracebackএবং তারপর:

try:
    ...
except Exception as e:
    print(traceback.print_tb(e.__traceback__))

আমি পাইথন ৩.7 ব্যবহার করছি।


3

জন্য পাইথন 3.5+ :

সুতরাং, আপনি অন্য কোনও ব্যতিক্রম হিসাবে আপনার ব্যতিক্রম থেকে স্ট্যাকট্রেস পেতে পারেন। traceback.TracebackExceptionএটির জন্য ব্যবহার করুন (কেবলমাত্র exআপনার ব্যতিক্রমের সাথে প্রতিস্থাপন করুন):

print("".join(traceback.TracebackException.from_exception(ex).format())

এটি করার জন্য একটি বর্ধিত উদাহরণ এবং অন্যান্য বৈশিষ্ট্য:

import traceback

try:
    1/0
except Exception as ex:
    print("".join(traceback.TracebackException.from_exception(ex).format()) == traceback.format_exc() == "".join(traceback.format_exception(type(ex), ex, ex.__traceback__))) # This is True !!
    print("".join(traceback.TracebackException.from_exception(ex).format()))

আউটপুটটি এরকম কিছু হবে:

True
Traceback (most recent call last):
  File "untidsfsdfsdftled.py", line 29, in <module>
    1/0
ZeroDivisionError: division by zero


1

যদি আপনার লক্ষ্য ব্যতিক্রম হয় এবং স্ট্যাকট্রেস বার্তাটি ঠিক দেখতে দেখতে পাইথনটি যখন পাইথন একটি ত্রুটি ছুড়ে দেয় তবে নিম্নলিখিত অজগর 2 + 3 উভয় ক্ষেত্রে নিম্নলিখিতটি কাজ করে:

import sys, traceback


def format_stacktrace():
    parts = ["Traceback (most recent call last):\n"]
    parts.extend(traceback.format_stack(limit=25)[:-2])
    parts.extend(traceback.format_exception(*sys.exc_info())[1:])
    return "".join(parts)

# EXAMPLE BELOW...

def a():
    b()


def b():
    c()


def c():
    d()


def d():
    assert False, "Noooh don't do it."


print("THIS IS THE FORMATTED STRING")
print("============================\n")

try:
    a()
except:
    stacktrace = format_stacktrace()
    print(stacktrace)

print("THIS IS HOW PYTHON DOES IT")
print("==========================\n")
a()

এটি format_stacktrace()স্ট্যাক থেকে শেষ কলটি সরিয়ে এবং বাকীগুলিতে যোগ দিয়ে কাজ করে। রান করার সময় উপরের উদাহরণটি নিম্নলিখিত আউটপুট দেয়:

THIS IS THE FORMATTED STRING
============================

Traceback (most recent call last):
  File "test.py", line 31, in <module>
    a()
  File "test.py", line 12, in a
    b()
  File "test.py", line 16, in b
    c()
  File "test.py", line 20, in c
    d()
  File "test.py", line 24, in d
    assert False, "Noooh don't do it."
AssertionError: Noooh don't do it.

THIS IS HOW PYTHON DOES IT
==========================

Traceback (most recent call last):
  File "test.py", line 38, in <module>
    a()
  File "test.py", line 12, in a
    b()
  File "test.py", line 16, in b
    c()
  File "test.py", line 20, in c
    d()
  File "test.py", line 24, in d
    assert False, "Noooh don't do it."
AssertionError: Noooh don't do it.

0

আমি নিম্নলিখিত সহায়ক শ্রেণীর সংজ্ঞায়িত করেছি:

import traceback
class TracedExeptions(object):
    def __init__(self):
        pass
    def __enter__(self):
        pass

    def __exit__(self, etype, value, tb):
      if value :
        if not hasattr(value, 'traceString'):
          value.traceString = "\n".join(traceback.format_exception(etype, value, tb))
        return False
      return True

যা আমি পরে এটি ব্যবহার করতে পারি:

with TracedExeptions():
  #some-code-which-might-throw-any-exception

এবং পরে এটি এর মতো গ্রাস করতে পারে:

def log_err(ex):
  if hasattr(ex, 'traceString'):
    print("ERROR:{}".format(ex.traceString));
  else:
    print("ERROR:{}".format(ex));

(পটভূমি: Promises এর সাথে একসাথে ব্যবহার করার কারণে আমি Exceptionহতাশ হয়ে পড়েছিলাম, যা দুর্ভাগ্যক্রমে এক জায়গায় উত্থাপিত ব্যতিক্রমগুলি অন্য স্থানে অন-রেজেক্টড হ্যান্ডলারের কাছে পৌঁছে দেয় এবং সুতরাং আসল অবস্থান থেকে ট্রেসব্যাক পাওয়া কঠিন)

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