当我捕获异常时,如何获取类型、文件和行号?

发布于 2024-08-01 16:35:51 字数 262 浏览 6 评论 0原文

捕获一个打印如下的异常:

Traceback (most recent call last):
  File "c:/tmp.py", line 1, in <module>
    4 / 0
ZeroDivisionError: integer division or modulo by zero

我想将其格式化为:

ZeroDivisonError, tmp.py, 1

Catching an exception that would print like this:

Traceback (most recent call last):
  File "c:/tmp.py", line 1, in <module>
    4 / 0
ZeroDivisionError: integer division or modulo by zero

I want to format it into:

ZeroDivisonError, tmp.py, 1

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

江湖彼岸 2024-08-08 16:35:51
import sys, os

try:
    raise NotImplementedError("No error")
except Exception as e:
    exc_type, exc_obj, exc_tb = sys.exc_info()
    fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
    print(exc_type, fname, exc_tb.tb_lineno)
import sys, os

try:
    raise NotImplementedError("No error")
except Exception as e:
    exc_type, exc_obj, exc_tb = sys.exc_info()
    fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
    print(exc_type, fname, exc_tb.tb_lineno)
何止钟意 2024-08-08 16:35:51

来源(Py v2.7.3)traceback.format_exception() 和调用/相关函数有很大帮助。 尴尬的是,我总是忘记阅读源代码。 我只是在徒劳地搜索类似细节后才这样做的。 一个简单的问题,“如何为异常重新创建与 Python 相同的输出,并具有所有相同的细节?” 这将使任何人 90% 以上都能找到他们想要的东西。 很沮丧,我想出了这个例子。 我希望它对其他人有帮助。 (这确实对我有帮助!;-)

import sys, traceback

traceback_template = '''Traceback (most recent call last):
  File "%(filename)s", line %(lineno)s, in %(name)s
%(type)s: %(message)s\n''' # Skipping the "actual line" item

# Also note: we don't walk all the way through the frame stack in this example
# see hg.python.org/cpython/file/8dffb76faacc/Lib/traceback.py#l280
# (Imagine if the 1/0, below, were replaced by a call to test() which did 1/0.)

try:
    1/0
except:
    # http://docs.python.org/2/library/sys.html#sys.exc_info
    exc_type, exc_value, exc_traceback = sys.exc_info() # most recent (if any) by default

    '''
    Reason this _can_ be bad: If an (unhandled) exception happens AFTER this,
    or if we do not delete the labels on (not much) older versions of Py, the
    reference we created can linger.

    traceback.format_exc/print_exc do this very thing, BUT note this creates a
    temp scope within the function.
    '''

    traceback_details = {
                         'filename': exc_traceback.tb_frame.f_code.co_filename,
                         'lineno'  : exc_traceback.tb_lineno,
                         'name'    : exc_traceback.tb_frame.f_code.co_name,
                         'type'    : exc_type.__name__,
                         'message' : exc_value.message, # or see traceback._some_str()
                        }

    del(exc_type, exc_value, exc_traceback) # So we don't leave our local labels/objects dangling
    # This still isn't "completely safe", though!
    # "Best (recommended) practice: replace all exc_type, exc_value, exc_traceback
    # with sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]

    print
    print traceback.format_exc()
    print
    print traceback_template % traceback_details
    print

对此查询的具体回答:

sys.exc_info()[0].__name__, os.path.basename(sys.exc_info()[2].tb_frame.f_code.co_filename), sys.exc_info()[2].tb_lineno

Source (Py v2.7.3) for traceback.format_exception() and called/related functions helps greatly. Embarrassingly, I always forget to Read the Source. I only did so for this after searching for similar details in vain. A simple question, "How to recreate the same output as Python for an exception, with all the same details?" This would get anybody 90+% to whatever they're looking for. Frustrated, I came up with this example. I hope it helps others. (It sure helped me! ;-)

import sys, traceback

traceback_template = '''Traceback (most recent call last):
  File "%(filename)s", line %(lineno)s, in %(name)s
%(type)s: %(message)s\n''' # Skipping the "actual line" item

# Also note: we don't walk all the way through the frame stack in this example
# see hg.python.org/cpython/file/8dffb76faacc/Lib/traceback.py#l280
# (Imagine if the 1/0, below, were replaced by a call to test() which did 1/0.)

try:
    1/0
except:
    # http://docs.python.org/2/library/sys.html#sys.exc_info
    exc_type, exc_value, exc_traceback = sys.exc_info() # most recent (if any) by default

    '''
    Reason this _can_ be bad: If an (unhandled) exception happens AFTER this,
    or if we do not delete the labels on (not much) older versions of Py, the
    reference we created can linger.

    traceback.format_exc/print_exc do this very thing, BUT note this creates a
    temp scope within the function.
    '''

    traceback_details = {
                         'filename': exc_traceback.tb_frame.f_code.co_filename,
                         'lineno'  : exc_traceback.tb_lineno,
                         'name'    : exc_traceback.tb_frame.f_code.co_name,
                         'type'    : exc_type.__name__,
                         'message' : exc_value.message, # or see traceback._some_str()
                        }

    del(exc_type, exc_value, exc_traceback) # So we don't leave our local labels/objects dangling
    # This still isn't "completely safe", though!
    # "Best (recommended) practice: replace all exc_type, exc_value, exc_traceback
    # with sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]

    print
    print traceback.format_exc()
    print
    print traceback_template % traceback_details
    print

In specific answer to this query:

sys.exc_info()[0].__name__, os.path.basename(sys.exc_info()[2].tb_frame.f_code.co_filename), sys.exc_info()[2].tb_lineno
请别遗忘我 2024-08-08 16:35:51

对我有用的最简单的形式。

import traceback

try:
    print(4/0)
except ZeroDivisionError:
    print(traceback.format_exc())

输出

Traceback (most recent call last):
  File "/path/to/file.py", line 51, in <module>
    print(4/0)
ZeroDivisionError: division by zero

Process finished with exit code 0

Simplest form that worked for me.

import traceback

try:
    print(4/0)
except ZeroDivisionError:
    print(traceback.format_exc())

Output

Traceback (most recent call last):
  File "/path/to/file.py", line 51, in <module>
    print(4/0)
ZeroDivisionError: division by zero

Process finished with exit code 0
风苍溪 2024-08-08 16:35:51

这是显示发生异常的行号的示例。

import sys
try:
    print(5/0)
except Exception as e:
    print('Error on line {}'.format(sys.exc_info()[-1].tb_lineno), type(e).__name__, e)

print('And the rest of program continues')

Here is an example of showing the line number of where exception takes place.

import sys
try:
    print(5/0)
except Exception as e:
    print('Error on line {}'.format(sys.exc_info()[-1].tb_lineno), type(e).__name__, e)

print('And the rest of program continues')
稳稳的幸福 2024-08-08 16:35:51

没有任何导入,但也不递归到导入的模块中:

try:
    raise TypeError("Hello, World!")  # line 2
except Exception as e:
    print(
        type(e).__name__,          # TypeError
        __file__,                  # /tmp/example.py
        e.__traceback__.tb_lineno  # 2
    )

$ python3 /tmp/example.py
TypeError /tmp/example.py 2

重申一下,这不能导入或模块工作,所以如果您导入X; 尝试: X.example(); 那么文件名和行号将指向包含 X.example() 的行,而不是内出现错误的行 em> X.example()。 如果有人知道如何轻松地从最后一个堆栈跟踪行获取文件名和行号(我期望类似 e[-1].filename 的东西,但没有这样的运气),请改进这个答案。

Without any imports, but also not recursing into imported modules:

try:
    raise TypeError("Hello, World!")  # line 2
except Exception as e:
    print(
        type(e).__name__,          # TypeError
        __file__,                  # /tmp/example.py
        e.__traceback__.tb_lineno  # 2
    )

$ python3 /tmp/example.py
TypeError /tmp/example.py 2

To reiterate, this does not work across imports or modules, so if you do import X; try: X.example(); then the filename and line number will point to the line containing X.example() instead of the line where it went wrong within X.example(). If anyone knows how to easily get the file name and line number from the last stack trace line (I expected something like e[-1].filename, but no such luck), please improve this answer.

冷︶言冷语的世界 2024-08-08 16:35:51
try:
    4/0
except Exception as exc:
    print("error: ",exc)
    print("error file info: ",exc.__traceback__.tb_frame)
    print("error line#: ",exc.__traceback__.tb_lineno)
try:
    4/0
except Exception as exc:
    print("error: ",exc)
    print("error file info: ",exc.__traceback__.tb_frame)
    print("error line#: ",exc.__traceback__.tb_lineno)
爺獨霸怡葒院 2024-08-08 16:35:51

您无需导入回溯即可实现此目的:

try:
    func1()
except Exception as ex:
    trace = []
    tb = ex.__traceback__
    while tb is not None:
        trace.append({
            "filename": tb.tb_frame.f_code.co_filename,
            "name": tb.tb_frame.f_code.co_name,
            "lineno": tb.tb_lineno
        })
        tb = tb.tb_next
    print(str({
        'type': type(ex).__name__,
        'message': str(ex),
        'trace': trace
    }))

输出:

{

  'type': 'ZeroDivisionError',
  'message': 'division by zero',
  'trace': [
    {
      'filename': '/var/playground/main.py',
      'name': '<module>',
      'lineno': 16
    },
    {
      'filename': '/var/playground/main.py',
      'name': 'func1',
      'lineno': 11
    },
    {
      'filename': '/var/playground/main.py',
      'name': 'func2',
      'lineno': 7
    },
    {
      'filename': '/var/playground/my.py',
      'name': 'test',
      'lineno': 2
    }
  ]
}

You could achieve this without having to import traceback:

try:
    func1()
except Exception as ex:
    trace = []
    tb = ex.__traceback__
    while tb is not None:
        trace.append({
            "filename": tb.tb_frame.f_code.co_filename,
            "name": tb.tb_frame.f_code.co_name,
            "lineno": tb.tb_lineno
        })
        tb = tb.tb_next
    print(str({
        'type': type(ex).__name__,
        'message': str(ex),
        'trace': trace
    }))

Output:

{

  'type': 'ZeroDivisionError',
  'message': 'division by zero',
  'trace': [
    {
      'filename': '/var/playground/main.py',
      'name': '<module>',
      'lineno': 16
    },
    {
      'filename': '/var/playground/main.py',
      'name': 'func1',
      'lineno': 11
    },
    {
      'filename': '/var/playground/main.py',
      'name': 'func2',
      'lineno': 7
    },
    {
      'filename': '/var/playground/my.py',
      'name': 'test',
      'lineno': 2
    }
  ]
}
对不⑦ 2024-08-08 16:35:51

这就是我用来获取文件名的方法。

__file__.__str__

总而言之,我创建了一个页面来显示错误。 出现异常时返回此值。

context={
                'details':'Type of error:{}:Function name:{}:Line number:{}'.format(exc_type, fname, exc_tb.tb_lineno),
                'error_details':str(e),
                'filename':__file__.__str__,
            })

发生异常时的外观:

在此处输入图像描述

This is what I used to get the file name.

__file__.__str__

To sum it, I created a page to show errors. Return this on exception.

context={
                'details':'Type of error:{}:Function name:{}:Line number:{}'.format(exc_type, fname, exc_tb.tb_lineno),
                'error_details':str(e),
                'filename':__file__.__str__,
            })

How it looks in case an exception occurs:

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文