Discussion:
[Twisted-Python] qt5 and twisted, reactor already installed, python 2.x
steven meier
2016-06-29 22:39:02 UTC
Permalink
hi,


ive got some twisted code that runs on its own
and some python code that also runs on its own,

now i would like to combine the two, so i added:

if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv) # your code to init QtCore
import qt5reactor
qt5reactor.install()
from twisted.internet import reactor



to use some qt reactor with twisted.
running the qt code with those lines also works.
but as soon as i import other code into this one i get:


python main_code.py
Gtk-Message: Failed to load module "canberra-gtk-module"
Traceback (most recent call last):
File "main_code.py", line 29, in <module>
qt5reactor.install()
File "/home/julius/.local/lib/python2.7/site-packages/qt5reactor.py",
line 412, in posixinstall
installReactor(p)
File
"/home/julius/.local/lib/python2.7/site-packages/twisted/internet/main.py", line 32, in installReactor
raise error.ReactorAlreadyInstalledError("reactor already
installed")
twisted.internet.error.ReactorAlreadyInstalledError: reactor already
installed




here is my code:
when importing get_main_page i get the error above...

import sys
from PyQt5 import QtWidgets
from untitled import Ui_MainWindow
#from webchat import get_main_page

class Main(QtWidgets.QMainWindow):

def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.setupSignals()

def button_1_Clicked(self):
self.ui.textbox_2.setText(self.ui.textbox_1.text())

def setupSignals(self):
#self.ui.textbox_1.textChanged.connect(self.textbox_1_Changed)
self.ui.button_1.clicked.connect(self.button_1_Clicked)




if __name__ == '__main__':
#app = QtWidgets.QApplication(sys.argv)

app = QtWidgets.QApplication(sys.argv) # your code to init QtCore
import qt5reactor
qt5reactor.install()
from twisted.internet import reactor
print "testing..."

#get_main_page()
window = Main()
window.show()
#sys.exit(app.exec_())
def printMe(argument):
print argument

def lala():
reactor.callLater(5, printMe, '123')


lala()
reactor.run()






webchat.py (containing get_main_page) starts with the lines:

from twisted.web.client import Agent, CookieAgent, getPage,
HTTPClientFactory
from bs4 import BeautifulSoup
import json
import urllib
import random
from myglobals import *
from twisted.internet.task import LoopingCall




how can i get a more "refined" error message, that actually tells me
which line is causing the error?

because as i said, the line 29 in main_code works when i do not import
get_main_page
Glyph
2016-06-29 23:01:17 UTC
Permalink
Post by steven meier
when importing get_main_page i get the error above...
import sys
from PyQt5 import QtWidgets
from untitled import Ui_MainWindow
#from webchat import get_main_page
You have to put the qt5reactor installation at the very top of the very first file that you run. What's happened here is that you imported some Twisted code that did 'from twisted.internet import reactor' at the top level, which unfortunately far too many modules do, before you installed the qt5 reactor.

For this and other reasons, you should always put your `if __name__ == '__main__'` block - if you have one at all - at the very top of your script, not the bottom. This blog post may be informative: https://moshez.wordpress.com/2016/06/07/__name__-__main__-considered-harmful/

-glyph
steven meier
2016-06-30 10:44:44 UTC
Permalink
Post by Glyph
Post by steven meier
when importing get_main_page i get the error above...
import sys
from PyQt5 import QtWidgets
from untitled import Ui_MainWindow
#from webchat import get_main_page
You have to put the qt5reactor installation at the very top of the
very first file that you run. What's happened here is that you
imported some Twisted code that did 'from twisted.internet import
reactor' at the top level, which unfortunately far too many modules
do, before you installed the qt5 reactor.
For this and other reasons, you should always put your `if __name__ ==
'__main__'` block - if you have one at all - at the very top of your
script, not the bottom. This blog post may be
informative: https://moshez.wordpress.com/2016/06/07/__name__-__main__-considered-harmful/
-glyph
_______________________________________________
thank you for the quick reply, you were right.
but because of the qt imports / Main class my file now basically has the
line:
from webchat import get_main_page

at the end with the rest unchanged....but at least it runs
steven meier
2016-06-30 10:49:00 UTC
Permalink
Post by Glyph
You have to put the qt5reactor installation at the very top of the
very first file that you run. What's happened here is that you
imported some Twisted code that did 'from twisted.internet import
reactor' at the top level, which unfortunately far too many modules
do, before you installed the qt5 reactor.
So twisted modules should not at all import the reactor but rely on the
user code todo that?
Glyph Lefkowitz
2016-06-30 22:09:20 UTC
Permalink
Post by steven meier
Post by Glyph
You have to put the qt5reactor installation at the very top of the
very first file that you run. What's happened here is that you
imported some Twisted code that did 'from twisted.internet import
reactor' at the top level, which unfortunately far too many modules
do, before you installed the qt5 reactor.
So twisted modules should not at all import the reactor but rely on the
user code todo that?
Yes. Unfortunately, lots of places do import the reactor directly today, but we have long since decided that this is a bad way to do things. This is why e.g. react <https://twistedmatrix.com/documents/16.2.0/api/twisted.internet.task.html#react> passes the reactor to your function as a parameter, so you can pass it on down to any other code that needs it.

-glyph
meejah
2016-06-30 23:22:29 UTC
Permalink
Post by Glyph Lefkowitz
Yes. Unfortunately, lots of places do import the reactor directly
today, but we have long since decided that this is a bad way to do
things. This is why e.g. react
<https://twistedmatrix.com/documents/16.2.0/api/twisted.internet.task.h
tml#react> passes the reactor to your function as a parameter, so you
can pass it on down to any other code that needs it.
As a "casual" user of Twisted, I was somewhat skeptical of this "pass
the reactor everywhere" approach -- but I did try to follow this advice
in txtorcon, and was rewarded with easy-to-write tests regarding timing,
which are (usually) a horror-show *and* I was rewarded with having to
think about "do I *really* need the reactor here?".

Now, sometimes you can compromise. For example, see my AddrMap class
which assigns a "self.scheduler" which is usually just gotten by
importing from twisted.internet.reactor -- *but* critically, the tests
can re-assign this:

https://github.com/meejah/txtorcon/blob/master/test/test_addrmap.py#L109

Ideally, this would have been passed-in via the __init__ but,
*shruggy-face*. The point being, you can incrementally upgrade to "the
better way".

Overall, I'm very sold on accessing "the reactor" via "self dot
something" rather than via imports *even if* the only reason ends up
being "because testing". It's pretty likely that some random user you've
never heard of has a similar use-case to that thing you needed to do in
that one test... (I've read this elsewhere, not my idea)

If nothing else, it will cause you to pause and consider "how will this
thing access the reactor", which will cause you to think about
concurrency issues... (Or, contrary-wise, classes which *don't* have a
self._reactor definitely do *not* need any thinking about concurrency --
which is also a big win).

In any case, my concurrency-hackles raise when I see ".. import
reactor". Best to localize these fears to "self._reactor".
--
meejah
Loading...