import imaplib2, time
from threading import *
# 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!
print "evernt is set"
self.event.set()
def join(self):
self.thread.join()
def test(self):
return self.thread.is_alive()
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!"
# Had to do this stuff in a try-finally, since some testing
# went a little wrong.....
try:
# Set the following two lines to your creds and server
M = imaplib2.IMAP4_SSL("mail.example.com")
M.login("mylogin","mypassword")
# We need to get out of the AUTH state, so we just select
# the INBOX.
M.select("INBOX")
# Start the Idler thread
idler = Idler(M)
idler.start()
# Because this is just an example, exit after 1 minute.
time.sleep(1*60)
finally:
# Clean up.
idler.stop()
idler.join()
M.close()
# This is important!
M.logout()
class Notifier(Logger):
def __init__(self, host, user, password, box='INBOX', debug=0, use_ssl=True):
self.irc = None
self.idler = None
self.M = None
self.messages = {}
self.cybersquatting = {}
while True:
try:
if use_ssl:
self.M = imaplib2.IMAP4_SSL(host, debug=debug)
else:
self.M = imaplib2.IMAP4(host, debug=debug)
self.M.login(user, password)
self.M.select(box)
self.idler = Idler(self.M, self)
self.idler.start()
while True:
# 这段代码一直执行,用来检查idler这个线程是否在活动
# 但有的时候代码在这儿会停止,不明白?
# 是不是idler thread还是is_alive?
if not self.idler.test():
raise ThreadDead()
try:
self.process_cybersquatting()
except:
pass
time.sleep(2)
except imaplib2.IMAP4.abort:
self.error("Disconnected. Trying again!")
except Exception as e:
self.error("imaplib2 except:{}".format(e)
time.sleep(2)
上面的代码Notifier有时会停止,找不到原因,现在觉得有几个可能
1.self.process_cybersquatting() 进入无限循环,这个不太可能,我查了好几遍,这个函数不可能无限循环的。另外这个不影响其它线程吧?
2.self.idler线程已经停止了,但self.idler.test()返回的还是True
每次都是到这一步def stop(self): 这个函数的时候再也不运行了。打印出evernt is set后,之后的代码再也没有任何响应了。
另外,有没有办法调试代码,让我知道到底程序卡到什么地方了,对于Python我还是初学者,请大家帮帮忙吧。
1
binux 2015-06-16 14:28:42 +08:00
如果
self.event.wait() 和 if self.needsync: 之间,callback 和 self.stop() 同时执行了,你猜会发生什么 |
2
9hills 2015-06-16 14:34:12 +08:00 via iPhone
Debug 可以用pdb
|
3
sbmzhcn OP @binux 能详细说说吗,同时执行了,`if not self.idler.test(): raise ThreadDead()` 这个会出现raise ThreadDead的吧,然后程序仍然可以重新运行啊。
|
5
binux 2015-06-16 14:53:32 +08:00
|
6
lilydjwg 2015-06-16 14:54:46 +08:00
没看到你的 Notifier 在哪里用了。
你有两个地方设置 Event。如果它们同时执行到的话,你会把它清除掉但是不停止。不要把一个同步对象用作两种不同的目的。 PS: 你对 Thread 的使用很奇怪。 |
9
sbmzhcn OP 问题我想我应该找到了,上面的人说的都不对应该。问题还是出在self.process_cybersquatting(), 由于socket产生了阻塞,导致一直等待状态。
具体的原因还没有证实,我等会用下异步socket,如果没问题,就是这个原因了。 |