线程Thread-4中的异常 - 查找原因或捕获异常

时间:2013-05-14 06:09:16

标签: python python-2.7

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

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

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

  3. .......

    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
    

2 个答案:

答案 0 :(得分:0)

尝试捕捉imaplib2.IMAP4.abort

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

答案 1 :(得分:0)

我试图解决同样的问题而且我已经成功了。

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

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

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