星期五, 7月 17, 2009

IMAP in Python - 3 (Error Handling)

前面的例子無法處理錯誤出現的情形,如果出現了錯誤,程式就會因為沒有呼叫到reactor.stop()造成程式卡住,再來看看twisted中如何處理錯誤呢?由於錯誤發生的時候,控制權可能已經不是當下那個function的了,所以一樣使用callback,而處理錯誤的callback稱之為errback。

直接來看例子:

class IMAPLogic:
def __init__(self, proto):
self.proto = proto
self.factory = proto.factory
self.logintries = 1

d = self.login()
d.addCallback(self.loggedin)
d.addErrback(self.loginerror)
d.addCallback(self.logout)
d.addCallback(self.stopreactor)

d.addErrback(self.errorhappen)

print "IMAPLogic.__init__returning."

只要對defered object呼叫addErrback,此errback function就會負責處理當時以上的function,也就是說loggedin()發生的錯誤由loginerror()處理,而logout()與stopreactor()的錯誤也由errorhappen()來處理。其實,如果在login()發生了在loginerror()無法處理的錯誤時,twisted會直接把錯誤丟給下一個errback,此例是loginerror()無法處理的錯誤就傳給errorhappen()>
那就再來看一下那兩個errback function:

def loginerror(self, failure):
print "Your loging failed (attemp %d times)." % self.logintries
if self.logintries >= 3:
print "You have tried to log in three times; I'm giving up."
return failure
self.logintries += 1

sys.stdout.write("username:")
self.factory.username = sys.stdin.readline().strip()
self.factory.password = getpass.getpass("password:")

d = self.login()
d.addErrback(self.loginerror)
return d

在這邊處理的是只有登入超過三次失敗的情形,如果超過三次等情形,就會直接return failure把錯誤傳接下去給errorhappen()。在此function的結尾有增加defered object呼叫自己,如果沒成功就繼續回來此function。


def errorhappen(self, failure):
print "An error occurred:", failure.getErrorMessage()
print "Because of the error, I am logging out and stopping reactor..."
d = self.logout()
d.addBoth(self.stopreactor)
return failure

此function是單純把failure的訊息印出來,然後logout(),並且無論logout成功失敗都要呼叫stopreactor()來把reactor.run()中止,避免程式掛著。
以下是程式的兩種output:

cacaegg@cacabook:~/workspace/NetworkProgram/src/IMAP$ t-error.py mx.mgt.ncu.edu.tw cacaegg
Enter password for cacaegg on mx.mgt.ncu.edu.tw:
I have successfully connected to the server!
Logging in...
IMAPLogic.__init__returning.
connectionMade returning
I'm logged in!
Logging out.
Stopping reactor.
cacaegg@cacabook:~/workspace/NetworkProgram/src/IMAP$ t-error.py mx.mgt.ncu.edu.tw cacaegg
Enter password for cacaegg on mx.mgt.ncu.edu.tw:
I have successfully connected to the server!
Logging in...
IMAPLogic.__init__returning.
connectionMade returning
Your loging failed (attemp 1 times).
username:ewfwfewf
password:
Logging in...
Your loging failed (attemp 2 times).
username:efwfew
password:
Logging in...
Your loging failed (attemp 3 times).
You have tried to log in three times; I'm giving up.
An error occurred: Authentication failed.
Because of the error, I am logging out and stopping reactor...
Logging out.
Unhandled error in Deferred:
Traceback (most recent call last):
Failure: twisted.mail.imap4.IMAP4Exception: Authentication failed.
Stopping reactor.


程式連結

沒有留言: