python - 从脚本中删除线程使用

标签 python ios python-2.7

我正在使用的下一个脚本用于使用 IMAP IDLE 监听 IMAP 连接,并且在很大程度上依赖于线程。消除踏板调用并仅使用主线程的最简单方法是什么? 作为一名新的 Python 开发人员,我尝试编辑 def __init__(self, conn): 方法,但错误越来越多

代码示例对我有很大帮助

#!/usr/local/bin/python2.7
print "Content-type: text/html\r\n\r\n";

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

# enter gmail login details here
USER="username@gmail.com"
PASSWORD="password"
# enter device token here
deviceToken = 'my device token x x x x x'
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 = 'certif.pem'
        theHost = ('gateway.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. 
    # Replace it with something better.
    def dosync(self):
        print "Got an event!"
        numUnseen = getUnseen()
        sendPushNotification(numUnseen)

# Had to do this stuff in a try-finally, since some testing 
# went a little wrong.....
while True:
    try:
        # Set the following two lines to your creds and server
        M = imaplib2.IMAP4_SSL("imap.gmail.com")
        M.login(USER, PASSWORD)
        M.debug = 4
        # We need to get out of the AUTH state, so we just select 
        # the INBOX.
        M.select("INBOX")
        numUnseen = getUnseen()
        sendPushNotification(numUnseen)

        typ, data = M.fetch(1, '(RFC822)')
        raw_email = data[0][1]

        import email
        email_message = email.message_from_string(raw_email)
        print email_message['Subject']

        #print M.status("INBOX", '(UNSEEN)')
        # Start the Idler thread
        idler = Idler(M)
        idler.start()


        # Sleep forever, one minute at a time
        while True:
            time.sleep(60)
    except imaplib2.IMAP4.abort:
      print("Disconnected.  Trying again.")   
    finally:
        # Clean up.
        #idler.stop() #Commented out to see the real error
        #idler.join() #Commented out to see the real error
        #M.close()    #Commented out to see the real error
        # This is important!
        M.logout()

最佳答案

据我所知,这段代码非常困惑,因为作者使用了 "imaplib2" project library这会强制使用此代码永远不会使用的线程模型。

只会创建一个线程,它不需要是一个线程,但可以选择imaplib2。但是,作为 imaplib2 documentation notes :

This module presents an almost identical API as that provided by the standard python library module imaplib, the main difference being that this version allows parallel execution of commands on the IMAP4 server, and implements the IMAP4rev1 IDLE extension. (imaplib2 can be substituted for imaplib in existing clients with no changes in the code, but see the caveat below.)

这使您看起来应该能够丢弃大部分 class Idler 并只使用连接 M。我建议您查看 Doug Hellman 的优秀 Python 本周模块 module imaplib在查看 official documentation 之前.您需要对代码进行逆向工程以找出其意图,但在我看来它是这样的:

  1. 打开与 GMail 的连接
  2. 检查收件箱中是否有未看到的邮件
  3. 计算来自 (2) 的未看到的消息
  4. 向 gateway.push.apple.com 上的某个服务发送一条虚拟消息
  5. 等待通知,转到 (2)

也许关于代码最有趣的事情是它似乎没有做任何事情,尽管 sendPushNotification(第 4 步)所做的是一个谜,并且使用 imaplib2 特定的一行服务:

self.M.idle(callback=callback)

使用了我在模块文档中没有看到的命名参数。你知道这段代码是否真的运行过吗?

除了不必要的复杂性之外,还有另一个放弃 imaplib2 的原因:它独立存在于 sourceforge 上和 PyPi两年前一位维护者声称“将尝试使其与原始版本保持同步”。你有哪一个?你会安装哪个?

关于python - 从脚本中删除线程使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16865668/

相关文章:

python - selenium.common.exceptions.WebDriverException : Message: 'Geckodriver' executable may have wrong permissions using GeckoDriver Firefox Selenium Python

python - Python 中的嵌套 float 组

ios - 解析检查是否为 nil

ios - 如何获取数组中的字典对象

python - 做批量索引时无法删除 Elasticsearch 中的停用词

python - 根据文件中的条件随机抽取文件样本

python - 当查询返回Null(无对象)时如何在django模板中显示 "nothing found"?

iOS - 从 AppDelegate 导航到 SWRevealViewController 的 FrontViewController

python - 运行 python 脚本时出现 "executable not specified"错误

Python - 在土耳其现在几点了?