[Twisted-Python] How can I make twisted and dbus work together?
![](https://secure.gravatar.com/avatar/330feaaa52fcfd8ca0e62a3fe1a7d500.jpg?s=120&d=mm&r=g)
Hello everyone, I am trying to write a imap mail fetcher base on twisted and dbus. I have written a simple fetcher without dbus functionality and it's working fine. However I got a problem while adding dbus. http://twistedmatrix.com/trac/ticket/1352 is the only article about how can twisted and dbus work together that I could get from google and I just followed its suggestion and added from twisted.internet import glib2reactor glib2reactor.install() to my code. As what I read from twisted API http://twistedmatrix.com/documents/current/api/twisted.internet.glib2reactor... "In order to use this support, simply do the following: | from twisted.internet import glib2reactor | glib2reactor.install() Then use twisted.internet APIs as usual. " I thought everything will be fine. But when I was running my code, I got a error: Traceback (most recent call last): File "dbustwisted.py", line 5, in <module> glib2reactor.install() File "/usr/lib/python2.5/site-packages/twisted/internet/glib2reactor.py", line 33, in install return gtk2reactor.install(False) File "/usr/lib/python2.5/site-packages/twisted/internet/gtk2reactor.py", line 270, in install installReactor(reactor) File "/usr/lib/python2.5/site-packages/twisted/internet/main.py", line 24, in installReactor "reactor already installed" AssertionError: reactor already installed I don't know what's wrong with it. This is my code, I have not add the dbus part yet and just test the glib2reactor. from twisted.mail import imap4 from twisted.internet import protocol, defer import email, os, time MAILPATH = "Mails" IMAPSERVER = "xxxxxxxxxxx" USERNAME = "xxxxx" PASSWORD = "xxxxx" class IMAPDownloadProtocol(imap4.IMAP4Client): def serverGreeting(self, capabilities): login = self.login(self.factory.username, self.factory.password) login.addCallback(self.__loggedIn) login.chainDeferred(self.factory.deferred) # any event that fires login will also fire factory.deferred def __loggedIn(self, result): return self.select(self.factory.mailbox).addCallback(self.__selectedMailbox) def __selectedMailbox(self, result): allMessages = imap4.MessageSet(1, None) # a set of messages from message number 1 to the end of the mailbox return self.fetchUID(allMessages, True).addCallback(self.__gotUIDs) # fetch a list of UID def __gotUIDs(self, uidResults): self.messageUIDs = [result['UID'] for result in uidResults.values( )] self.messageCount = len(self.messageUIDs) print "INFO: %i messages in %s." % (self.messageCount, self.factory.mailbox) return self.fetchNextMessage( ) # start to download the message one by one def fetchNextMessage(self): if self.messageUIDs: nextUID = self.messageUIDs.pop(0) messageListToAnalysis = imap4.MessageSet(nextUID) # creates a MessageSet matching only that message's UID return self.fetchAll(messageListToAnalysis, True).addCallback(self.__gotIndex) # fetchAll - fetching the UID, flags, size, date, envelope # UID keyword set to true to tell the server that the MessageSet is referring to messages by UID, not sequence number else: return self.logout( ).addCallback(lambda _: self.transport.loseConnection( )) def __gotIndex(self, indexResults): index = indexResults.values() index_details = index[0] UID = index_details['UID'] flags = index_details['FLAGS'] size = index_details['RFC822.SIZE'] date = index_details['INTERNALDATE'] envelope = index_details['ENVELOPE'] title = envelope[1] sender = envelope[3] temp = [] # replace None in the envelope as "Empty", because None is a key word in python for element in sender[0]: if element != None: temp += [element] if element == None: temp += ["Empty"] sender = temp if flags == []: flags = ['\\Unseen'] print "INFO: Downloading message %i of %i" % (self.messageCount-len(self.messageUIDs), self.messageCount) messageListToFetch = imap4.MessageSet(UID) return self.fetchMessage(messageListToFetch, True).addCallback(self.__gotMessage, UID) def __gotMessage(self, fetchResults, UID): messageData = fetchResults.values( )[0]['RFC822'] self.factory.handleMessage(messageData, UID) return self.fetchNextMessage( ) # fetch next message def connectionLost(self, reason): if not self.factory.deferred.called: # connection was lost unexpectedly! self.factory.deferred.errback(reason) class IMAPDownloadFactory(protocol.ClientFactory): protocol = IMAPDownloadProtocol def __init__(self, username, password, mailbox, path): self.username = username self.password = password self.mailbox = mailbox self.path = path self.deferred = defer.Deferred( ) def handleMessage(self, messageData, UID): mailFile = os.path.join(path, UID) output = file(mailFile, 'w+b') parsedMessage = email.message_from_string(messageData) output.write(parsedMessage.as_string(unixfrom=True)) def startedConnecting(self, connector): print "INFO: Connection start" def clientConnectionFailed(self, connection, reason): self.deferred.errback(reason) def clientConnectionLost(self, connection, reason): print "INFO: Connection stop" #connection.connect() if __name__ == "__main__": from twisted.internet import glib2reactor glib2reactor.install() ################################################ # I added the 2 lines here and made the program crash ################################################ from twisted.internet import reactor import sys, getpass server = IMAPSERVER user = USERNAME mailbox = "Inbox" path = MAILPATH password = PASSWORD factory = IMAPDownloadFactory(user, password, mailbox, path) reactor.connectTCP(server, 143, factory) reactor.run( ) I am new to twisted, dbus even python, any helps will be appreciated. Regards Huisan ---------------------------------------------------------------- This message was sent using IMP, the Internet Messaging Program.
![](https://secure.gravatar.com/avatar/1d7efa864527c4118a418f07c5d49887.jpg?s=120&d=mm&r=g)
On Wed, 2008-01-16 at 17:28 +1100, hwan2265@mail.usyd.edu.au wrote:
But when I was running my code, I got a error:
Traceback (most recent call last): File "dbustwisted.py", line 5, in <module> glib2reactor.install() File "/usr/lib/python2.5/site-packages/twisted/internet/glib2reactor.py", line 33, in install return gtk2reactor.install(False) File "/usr/lib/python2.5/site-packages/twisted/internet/gtk2reactor.py", line 270, in install installReactor(reactor) File "/usr/lib/python2.5/site-packages/twisted/internet/main.py", line 24, in installReactor "reactor already installed" AssertionError: reactor already installed
I suspect your problem may be here:
if __name__ == "__main__": from twisted.internet import glib2reactor glib2reactor.install() ################################################ # I added the 2 lines here and made the program crash ################################################
from twisted.internet import reactor ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You've already imported glib2reactor, so you shouldn't import the default reactor as well. Try removing this line. -- Justin Warren <daedalus@eigenmagic.com>
![](https://secure.gravatar.com/avatar/44e3f98a2f3b7213d5f14b558a849dd2.jpg?s=120&d=mm&r=g)
Justin Warren wrote:
On Wed, 2008-01-16 at 17:28 +1100, hwan2265@mail.usyd.edu.au wrote:
But when I was running my code, I got a error:
Traceback (most recent call last): File "dbustwisted.py", line 5, in <module> glib2reactor.install() File "/usr/lib/python2.5/site-packages/twisted/internet/glib2reactor.py", line 33, in install return gtk2reactor.install(False) File "/usr/lib/python2.5/site-packages/twisted/internet/gtk2reactor.py", line 270, in install installReactor(reactor) File "/usr/lib/python2.5/site-packages/twisted/internet/main.py", line 24, in installReactor "reactor already installed" AssertionError: reactor already installed
I suspect your problem may be here:
if __name__ == "__main__": from twisted.internet import glib2reactor glib2reactor.install() ################################################ # I added the 2 lines here and made the program crash ################################################
from twisted.internet import reactor ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You've already imported glib2reactor, so you shouldn't import the default reactor as well. Try removing this line.
Actually, twisted.internet.reactor is quite magic. It is always the installed reactor. However, if there is no reactor installed the first time it is imported it will automatically install the default (select) reactor. I suspect that the real cause of the problem is that something is doing a "from twisted.internet import reactor", causing the select reactor to be installed, before the above code is getting the chance to install the glib2reactor. Looking at the code it must be a Twisted module that is the culprit. - Matt -- Matt Goodall Technical Director, Pollenation Internet Ltd Registered Number: 4382123 Registered Office: 237 Lidgett Lane, Leeds, West Yorkshire, LS17 6QR A member of the Brunswick MCL Group of Companies w: http://www.pollenation.net/ e: matt@pollenation.net t: +44 (0) 113 2252500 This message may be confidential and the views expressed may not reflect the views of my employers. Please read http://eudaimon-group.com/email if you are uncertain what this means.
![](https://secure.gravatar.com/avatar/44e3f98a2f3b7213d5f14b558a849dd2.jpg?s=120&d=mm&r=g)
Matt Goodall wrote:
Justin Warren wrote:
On Wed, 2008-01-16 at 17:28 +1100, hwan2265@mail.usyd.edu.au wrote:
But when I was running my code, I got a error:
Traceback (most recent call last): File "dbustwisted.py", line 5, in <module> glib2reactor.install() File "/usr/lib/python2.5/site-packages/twisted/internet/glib2reactor.py", line 33, in install return gtk2reactor.install(False) File "/usr/lib/python2.5/site-packages/twisted/internet/gtk2reactor.py", line 270, in install installReactor(reactor) File "/usr/lib/python2.5/site-packages/twisted/internet/main.py", line 24, in installReactor "reactor already installed" AssertionError: reactor already installed I suspect your problem may be here:
if __name__ == "__main__": from twisted.internet import glib2reactor glib2reactor.install() ################################################ # I added the 2 lines here and made the program crash ################################################
from twisted.internet import reactor ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You've already imported glib2reactor, so you shouldn't import the default reactor as well. Try removing this line.
Actually, twisted.internet.reactor is quite magic. It is always the installed reactor. However, if there is no reactor installed the first time it is imported it will automatically install the default (select) reactor.
I suspect that the real cause of the problem is that something is doing a "from twisted.internet import reactor", causing the select reactor to be installed, before the above code is getting the chance to install the glib2reactor.
Looking at the code it must be a Twisted module that is the culprit.
And the offending module is ... twisted.protocols.policies. Attached is a patch (I'll submit it to Trac as a ticket, too.) - Matt -- Matt Goodall Technical Director, Pollenation Internet Ltd
![](https://secure.gravatar.com/avatar/44e3f98a2f3b7213d5f14b558a849dd2.jpg?s=120&d=mm&r=g)
Matt Goodall wrote:
Matt Goodall wrote:
Justin Warren wrote:
On Wed, 2008-01-16 at 17:28 +1100, hwan2265@mail.usyd.edu.au wrote:
But when I was running my code, I got a error:
Traceback (most recent call last): File "dbustwisted.py", line 5, in <module> glib2reactor.install() File "/usr/lib/python2.5/site-packages/twisted/internet/glib2reactor.py", line 33, in install return gtk2reactor.install(False) File "/usr/lib/python2.5/site-packages/twisted/internet/gtk2reactor.py", line 270, in install installReactor(reactor) File "/usr/lib/python2.5/site-packages/twisted/internet/main.py", line 24, in installReactor "reactor already installed" AssertionError: reactor already installed I suspect your problem may be here:
if __name__ == "__main__": from twisted.internet import glib2reactor glib2reactor.install() ################################################ # I added the 2 lines here and made the program crash ################################################
from twisted.internet import reactor ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You've already imported glib2reactor, so you shouldn't import the default reactor as well. Try removing this line. Actually, twisted.internet.reactor is quite magic. It is always the installed reactor. However, if there is no reactor installed the first time it is imported it will automatically install the default (select) reactor.
I suspect that the real cause of the problem is that something is doing a "from twisted.internet import reactor", causing the select reactor to be installed, before the above code is getting the chance to install the glib2reactor.
Looking at the code it must be a Twisted module that is the culprit.
And the offending module is ... twisted.protocols.policies. Attached is a patch (I'll submit it to Trac as a ticket, too.)
Grepping the Twisted code suggests this is a "problem" that is not really worth trying to fix fully. It's probably best to just avoid the problem by making sure you get to install your choice of reactor before anything else. Of course, if you use the twistd daemon installing a specific reactor at the correct time is easy, by using the --reactor flag. - Matt
![](https://secure.gravatar.com/avatar/426d6dbf6554a9b3fca1fd04e6b75f38.jpg?s=120&d=mm&r=g)
Grepping the Twisted code suggests this is a "problem" that is not really worth trying to fix fully. It's probably best to just avoid the problem by making sure you get to install your choice of reactor before anything else.
When I ran into this issue and asked, that is what I was told. i.e. in real terms this means: #!/usr/bin/python # DO THIS BEFORE *ANYTHING* ELSE!!! from twisted.internet import glib2reactor glib2reactor.install() # only then start importing things from twisted.internet import defer from twisted.python import utils # ...etc
Of course, if you use the twistd daemon installing a specific reactor at the correct time is easy, by using the --reactor flag.
![](https://secure.gravatar.com/avatar/450aeb9ce64675fb7eb9c08f0b271215.jpg?s=120&d=mm&r=g)
hi, you have to install glib2reactor before importing any other modules to prevent them from importing the default reactor (which is the SelectReactor on linux) so simply put from twisted.internet import glib2reactor glib2reactor.install() on top of your script/module and it should work as expected :wq buz On Wed, Jan 16, 2008 at 05:28:38PM +1100, hwan2265@mail.usyd.edu.au wrote:
Hello everyone,
I am trying to write a imap mail fetcher base on twisted and dbus. I have written a simple fetcher without dbus functionality and it's working fine. However I got a problem while adding dbus.
http://twistedmatrix.com/trac/ticket/1352 is the only article about how can twisted and dbus work together that I could get from google and I just followed its suggestion and added
from twisted.internet import glib2reactor glib2reactor.install()
to my code.
As what I read from twisted API http://twistedmatrix.com/documents/current/api/twisted.internet.glib2reactor... "In order to use this support, simply do the following:
| from twisted.internet import glib2reactor | glib2reactor.install()
Then use twisted.internet APIs as usual. " I thought everything will be fine.
But when I was running my code, I got a error:
Traceback (most recent call last): File "dbustwisted.py", line 5, in <module> glib2reactor.install() File "/usr/lib/python2.5/site-packages/twisted/internet/glib2reactor.py", line 33, in install return gtk2reactor.install(False) File "/usr/lib/python2.5/site-packages/twisted/internet/gtk2reactor.py", line 270, in install installReactor(reactor) File "/usr/lib/python2.5/site-packages/twisted/internet/main.py", line 24, in installReactor "reactor already installed" AssertionError: reactor already installed
I don't know what's wrong with it. This is my code, I have not add the dbus part yet and just test the glib2reactor.
from twisted.mail import imap4 from twisted.internet import protocol, defer import email, os, time
MAILPATH = "Mails" IMAPSERVER = "xxxxxxxxxxx" USERNAME = "xxxxx" PASSWORD = "xxxxx"
class IMAPDownloadProtocol(imap4.IMAP4Client):
def serverGreeting(self, capabilities): login = self.login(self.factory.username, self.factory.password) login.addCallback(self.__loggedIn) login.chainDeferred(self.factory.deferred) # any event that fires login will also fire factory.deferred
def __loggedIn(self, result): return self.select(self.factory.mailbox).addCallback(self.__selectedMailbox)
def __selectedMailbox(self, result): allMessages = imap4.MessageSet(1, None) # a set of messages from message number 1 to the end of the mailbox return self.fetchUID(allMessages, True).addCallback(self.__gotUIDs) # fetch a list of UID
def __gotUIDs(self, uidResults): self.messageUIDs = [result['UID'] for result in uidResults.values( )] self.messageCount = len(self.messageUIDs) print "INFO: %i messages in %s." % (self.messageCount, self.factory.mailbox) return self.fetchNextMessage( ) # start to download the message one by one
def fetchNextMessage(self): if self.messageUIDs: nextUID = self.messageUIDs.pop(0) messageListToAnalysis = imap4.MessageSet(nextUID) # creates a MessageSet matching only that message's UID return self.fetchAll(messageListToAnalysis, True).addCallback(self.__gotIndex) # fetchAll - fetching the UID, flags, size, date, envelope # UID keyword set to true to tell the server that the MessageSet is referring to messages by UID, not sequence number else: return self.logout( ).addCallback(lambda _: self.transport.loseConnection( ))
def __gotIndex(self, indexResults): index = indexResults.values() index_details = index[0]
UID = index_details['UID'] flags = index_details['FLAGS'] size = index_details['RFC822.SIZE'] date = index_details['INTERNALDATE'] envelope = index_details['ENVELOPE']
title = envelope[1] sender = envelope[3] temp = [] # replace None in the envelope as "Empty", because None is a key word in python for element in sender[0]: if element != None: temp += [element] if element == None: temp += ["Empty"] sender = temp
if flags == []: flags = ['\\Unseen']
print "INFO: Downloading message %i of %i" % (self.messageCount-len(self.messageUIDs), self.messageCount) messageListToFetch = imap4.MessageSet(UID) return self.fetchMessage(messageListToFetch, True).addCallback(self.__gotMessage, UID)
def __gotMessage(self, fetchResults, UID): messageData = fetchResults.values( )[0]['RFC822'] self.factory.handleMessage(messageData, UID) return self.fetchNextMessage( ) # fetch next message
def connectionLost(self, reason): if not self.factory.deferred.called: # connection was lost unexpectedly! self.factory.deferred.errback(reason)
class IMAPDownloadFactory(protocol.ClientFactory): protocol = IMAPDownloadProtocol
def __init__(self, username, password, mailbox, path): self.username = username self.password = password self.mailbox = mailbox self.path = path self.deferred = defer.Deferred( )
def handleMessage(self, messageData, UID): mailFile = os.path.join(path, UID) output = file(mailFile, 'w+b') parsedMessage = email.message_from_string(messageData) output.write(parsedMessage.as_string(unixfrom=True))
def startedConnecting(self, connector): print "INFO: Connection start"
def clientConnectionFailed(self, connection, reason): self.deferred.errback(reason)
def clientConnectionLost(self, connection, reason): print "INFO: Connection stop" #connection.connect()
if __name__ == "__main__": from twisted.internet import glib2reactor glib2reactor.install() ################################################ # I added the 2 lines here and made the program crash ################################################
from twisted.internet import reactor import sys, getpass
server = IMAPSERVER user = USERNAME mailbox = "Inbox" path = MAILPATH password = PASSWORD
factory = IMAPDownloadFactory(user, password, mailbox, path) reactor.connectTCP(server, 143, factory) reactor.run( )
I am new to twisted, dbus even python, any helps will be appreciated.
Regards Huisan
---------------------------------------------------------------- This message was sent using IMP, the Internet Messaging Program.
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
-- If Bill Gates had a penny for every time Windows crashed......Oh wait, he does. GnuPG Fingerprint: 2FFF FC48 C7DF 1EA0 00A0 FD53 8C35 FD2E 6908 7B82
participants (5)
-
Bastian Winkler
-
hwan2265@mail.usyd.edu.au
-
Justin Warren
-
Matt Goodall
-
Phil Mayers