在循环中捕获异常追踪并在脚本末尾抛出错误

2 投票
1 回答
1497 浏览
提问于 2025-04-18 17:36

我想要捕捉所有的错误,然后在脚本结束时显示所有的错误信息...

我有一个主脚本,它会调用我的子脚本,比如说:

    errors = open('MISC/ERROR(S).txt', 'a')

    try:
        execfile("SUBSCRIPTS/Test1.py", {})
    except Exception:
        ## Spread over two calls of errors.write for readability in code...
        errors.write(strftime('%d/%m/%Y %H:%M:%S') + "\n")
        errors.write(traceback.format_exc() + '\n\n')

    try:
        execfile("SUBSCRIPTS/Test2.py", {})
    except Exception:
        ## Spread over two calls of errors.write for readability in code...
        errors.write(strftime('%d/%m/%Y %H:%M:%S') + "\n")
        errors.write(traceback.format_exc() + '\n\n')

    errors.close()

这个脚本使用了 traceback 模块来获取脚本中的错误信息...

在下一个例子中,我当前的脚本大概是这样的:

for x in y:
    if "example" in x:
        for tweet in tweetlist:
            # Try
            try:
                twitter.update_status(status=tweet)
                # Do some other stuff here if it suceeeds like...
                print "oo example worked"
            # Damn it failed, grab the whole traceback?
            except Exception as reason:
                FailedTweet = True

# Do some other stuff here like...
print "I did other stuff"

if FailedTweet:
    print reason # Printing the reason because I don't know how to throw the exception error (full error)

基本上有一个大循环,可能会在这行出错:twitter.update_status(status=tweet)。如果出错了,我想要捕捉到错误信息 可能会有多个错误,因为它在循环中,然后当脚本结束时,我想把所有的错误信息发送回主脚本,这样主脚本就可以把它们全部写入错误文件。

这是从第一段代码中写入文件的错误示例:

# 17/08/2014 12:30:00
# Traceback (most recent call last):
#   File "C:\Main.py", line 117, in execute_subscripts
#     execfile("SUBSCRIPTS/Test1.py", {})
#   File "SUBSCRIPTS/Test1.py", line 440, in <module>
#     twitter.update_status(status=string)
#   File "C:\Python27\lib\site-packages\twython\endpoints.py", line 90, in update_status
#     return self.post('statuses/update', params=params)
#   File "C:\Python27\lib\site-packages\twython\api.py", line 234, in post
#     return self.request(endpoint, 'POST', params=params, version=version)
#   File "C:\Python27\lib\site-packages\twython\api.py", line 224, in request
#     content = self._request(url, method=method, params=params, api_call=url)
#   File "C:\Python27\lib\site-packages\twython\api.py", line 194, in _request
#     retry_after=response.headers.get('retry-after'))
# TwythonError: Twitter API returned a 403 (Forbidden), This request looks like it might be automated. To protect our users from spam and other malicious activity, we can't complete this action right now. Please try again later.

我该怎么做到这一点呢,这有点难以解释,如果有什么不明白的地方请问我。

1 个回答

3

只需要把错误追踪的数据保存在一个列表里,然后在循环结束后打印这个列表的内容。

import traceback

reasons = []
for x in y:
    if "example" in x:
        for tweet in tweetlist:
            # Try
            try:
                twitter.update_status(status=tweet)
                # Do some other stuff here if it suceeeds like...
                print "oo example worked"
            # Damn it failed, grab the whole traceback?
            except Exception:
                reasons.append(traceback.format_exc())

# Do some other stuff here like...
print "I did other stuff"

for reason in reasons:
    print reason

# If you want to raise a single exception that shows the traceback for
# each exception, you can do this:
class ChainedException(Exception):
    def __init__(self, msg):
        msg = "The following exceptions occurred:\n\n{}".format(msg)

if reasons:
    raise ChainedException('\n'.join(reasons))

下面是使用 ChainedException 的例子:

reasons = []
for i in range(5):
    try:
        raise Exception("Blah {}".format(i))
    except Exception:
        reasons.append(traceback.format_exc())

if reasons:
    raise ChainedException("\n".join(reasons))

输出结果:

Traceback (most recent call last):
  File "ok.py", line 17, in <module>
    raise ChainedException("\n".join(reasons))
__main__.ChainedException: The following exceptions occurred:

Traceback (most recent call last):
  File "ok.py", line 12, in <module>
    raise Exception("Blah {}".format(i))
Exception: Blah 0

Traceback (most recent call last):
  File "ok.py", line 12, in <module>
    raise Exception("Blah {}".format(i))
Exception: Blah 1

Traceback (most recent call last):
  File "ok.py", line 12, in <module>
    raise Exception("Blah {}".format(i))
Exception: Blah 2

Traceback (most recent call last):
  File "ok.py", line 12, in <module>
    raise Exception("Blah {}".format(i))
Exception: Blah 3

Traceback (most recent call last):
  File "ok.py", line 12, in <module>
    raise Exception("Blah {}".format(i))
Exception: Blah 4

补充:

如果你真的只关心从所有错误中抛出一个单独的错误,可以这样做:

import traceback

reason = None
for x in y:
    if "example" in x:
        for tweet in tweetlist:
            # Try
            try:
                twitter.update_status(status=tweet)
                # Do some other stuff here if it suceeeds like...
                print "oo example worked"
            # Damn it failed, grab the whole traceback?
            except Exception:
                reason = sys.exc_info() # We're not putting it in a list because you only care about one.

# Do some other stuff here like...
print "I did other stuff"

if reason:
    raise reason[0], reason[1], reason[2]

请注意,这只适用于 Python 2.x。如果你使用的是 Python 3.x,就需要这样做:

if reason:
    raise reason[1].with_traceback(reason[2])

撰写回答