【问题标题】:Exception in thread Thread-4 - finding the reason or catch the exception线程 Thread-4 中的异常 - 查找原因或捕获异常
【发布时间】:2013-05-08 07:46:51
【问题描述】:

我正在我的服务器上运行此脚本,以便在新邮件到达时发送推送通知。它工作得很好,但有时脚本会因以下错误而崩溃。我不知道它为什么会崩溃,我自己也无法重现它。当它失败时,它不会进入 except 部分。 我试过了:except self.abort:except M.abort:except M.error:

  1. 知道为什么会崩溃吗?

  2. 对于短期解决方案,是否可以终止所有线程并从 except 部分重新启动脚本?

.......

import socket, ssl, json, struct, re
import imaplib2, time
from threading import *

# enter gmail login details here
USER="YOUR.NAME@gmail.com"
PASSWORD="YOUR-GMAIL-PASSWORD"
# enter device token here
deviceToken = 'XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX '
deviceToken = deviceToken.replace(' ','').decode('hex')
currentBadgeNum = -1

def getUnseen():
    (resp, data) = M.status("INBOX", '(UNSEEN)')
    print data
    return int(re.findall("UNSEEN (\d)*\)", data[0])[0])    

def sendPushNotification(badgeNum):
    global currentBadgeNum, deviceToken
    if badgeNum != currentBadgeNum:
        currentBadgeNum = badgeNum
        thePayLoad = {
             'aps': {
        #          'alert':'Hello world!',
                  'sound':'',
                  'badge': badgeNum,
                  },
             'test_data': { 'foo': 'bar' },
             }
        theCertfile = 'certfile.pem'
        theHost = ('gateway.sandbox.push.apple.com', 2195)

        data = json.dumps(thePayLoad)
        theFormat = '!BH32sH%ds' % len(data)
        theNotification = struct.pack(theFormat, 0, 32, deviceToken, len(data), data)

        ssl_sock = ssl.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM), certfile=theCertfile)
        ssl_sock.connect(theHost)
        ssl_sock.write(theNotification)
        ssl_sock.close()
        print "Sent Push alert."

# This is the threading object that does all the waiting on 
# the event
class Idler(object):
    def __init__(self, conn):
        self.thread = Thread(target=self.idle)
        self.M = conn
        self.event = Event()

    def start(self):
        self.thread.start()

    def stop(self):
        # This is a neat trick to make thread end. Took me a 
        # while to figure that one out!
        self.event.set()

    def join(self):
        self.thread.join()

    def idle(self):
        # Starting an unending loop here
        while True:
            # This is part of the trick to make the loop stop 
            # when the stop() command is given
            if self.event.isSet():
                return
            self.needsync = False
            # A callback method that gets called when a new 
            # email arrives. Very basic, but that's good.
            def callback(args):
                if not self.event.isSet():
                    self.needsync = True
                    self.event.set()
            # Do the actual idle call. This returns immediately, 
            # since it's asynchronous.
            self.M.idle(callback=callback)
            # This waits until the event is set. The event is 
            # set by the callback, when the server 'answers' 
            # the idle call and the callback function gets 
            # called.
            self.event.wait()
            # Because the function sets the needsync variable,
            # this helps escape the loop without doing 
            # anything if the stop() is called. Kinda neat 
            # solution.
            if self.needsync:
                self.event.clear()
                self.dosync()

    # The method that gets called when a new email arrives. 
    def dosync(self):
        print "Got an event!"
        numUnseen = getUnseen()
        sendPushNotification(numUnseen)

try:
    # Set the following two lines to your creds and server
    print 'starting'
    global M
    M = imaplib2.IMAP4_SSL("imap.gmail.com")
    M.login(USER, PASSWORD)
    # We need to get out of the AUTH state, so we just select 
    # the INBOX.
    #M.list()
    M.select('INBOX', readonly=True)
    numUnseen = getUnseen()
    getText()
    #print M.status("INBOX", '(UNSEEN)')
    # Start the Idler thread
    sendPushNotification(numUnseen)
    idler = Idler(M)
    idler.start()
    # Sleep forever, one minute at a time
    while True:
        time.sleep(60)

except self.abort:
    print 'we had a problem, dont worry! Ill fix it!'
    idler = Idler(M)
finally:
    # Clean up.
    idler.stop()
    idler.join()
    M.close()
    # This is important!
    M.logout()

.....................

.....................

  17:35.99 imap.gmail.com reader last 20 log messages:
  17:36.02 imap.gmail.com handler last 20 log messages:
Got an event!
Exception in thread Thread-4:
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/threading.py", line 551, in __bootstrap_inner
    self.run()
  File "/usr/local/lib/python2.7/threading.py", line 504, in run
    self.__target(*self.__args, **self.__kwargs)
  File "serverx.py", line 229, in idle
    self.dosync()
  File "serverx.py", line 235, in dosync
    numUnseen = getUnseen()
  File "serverx.py", line 150, in getUnseen
    (resp, data) = M.status("INBOX", '(UNSEEN)')
  File "/home/myuser/lib/python2.7/imaplib2/imaplib2.py", line 1121, in status
    return self._simple_command(name, mailbox, names, **kw)
  File "/home/myuser/lib/python2.7/imaplib2/imaplib2.py", line 1607, in _simple_command
    return self._command_complete(self._command(name, *args), kw)
  File "/home/myuser/lib/python2.7/imaplib2/imaplib2.py", line 1305, in _command
    raise self.abort('connection closed')
abort: connection closed

【问题讨论】:

    标签: python python-2.7


    【解决方案1】:

    尝试捕捉imaplib2.IMAP4.abort

    try:
        # ...
    except imaplib2.IMAP4.abort:
        # Oh no! An error!
    

    【讨论】:

    • 我会,但我怎样才能从除了里面重新启动脚本?
    • @EXEC_BAD_ACCESS:您可能希望在循环中运行try。当/如果它失败时,你会想要关闭现有的连接,(也许)稍等片刻,然后再次进入try 并重新连接。
    • 抱歉这个愚蠢的问题(python 新手)如何从except 内部再次运行try
    • @EXEC_BAD_ACCESS:如果整个try/except 处于循环中,而您只是忽略了来自except 的异常,它就会再次循环。
    • @EXEC_BAD_ACCESS: pass 实际上没有任何事情; pass 真的只意味着“什么都不做”。它存在的原因是,如果你有一个不想做任何事情的块,你可以显式使用它,因为你不能有一个 true 空块(因为这可能是无意的,所以会导致语法错误)。简而言之,无论是pass 还是其他,都无所谓;如果您不想做任何其他事情,您只需将pass 放在那里即可。
    【解决方案2】:

    我尝试过解决同样的问题,我成功了。

    您需要用try-except 包装self.M.idle(callback=callback),然后在主线程中重新引发它。然后通过在主线程中重新运行代码来重新启动连接来处理异常。

    您可以在此答案中找到解决方案的更多详细信息和可能的原因:https://stackoverflow.com/a/50163971/1544154

    完整的解决方案在这里:https://www.github.com/Elijas/email-notifier

    【讨论】:

      猜你喜欢
      • 2012-11-12
      • 1970-01-01
      • 2021-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-17
      • 1970-01-01
      相关资源
      最近更新 更多