[Twisted-Python] running code on its own and importing, howto install a different reactor?
hi, i ran into this issue, i can run the code on its own "python working_code.py", but i cant import it...how do you fit the reactor in this scenario? python main_code.py Unhandled error in Deferred: Traceback (most recent call last): File "/home/julius/.local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1274, in unwindGenerator return _inlineCallbacks(None, gen, Deferred()) File "/home/julius/.local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1128, in _inlineCallbacks result = g.send(result) File "/home/julius/code/python/qt5-python2.x/example/working_code.py", line 7, in print_it arg = yield terrific_method() File "/home/julius/.local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1274, in unwindGenerator return _inlineCallbacks(None, gen, Deferred()) --- <exception caught here> --- File "/home/julius/.local/lib/python2.7/site-packages/twisted/internet/defer.py", line 1128, in _inlineCallbacks result = g.send(result) File "/home/julius/code/python/qt5-python2.x/example/working_code.py", line 14, in terrific_method reactor.callLater(2, d.callback, 2) exceptions.NameError: global name 'reactor' is not defined cat main_code.py import qt5reactor qt5reactor.install() from twisted.internet import reactor from working_code import print_it print_it() cat working_code.py from twisted.internet.defer import inlineCallbacks, Deferred, returnValue @inlineCallbacks def print_it(): arg = yield terrific_method() print arg @inlineCallbacks def terrific_method(): d = Deferred() reactor.callLater(2, d.callback, 2) result = yield d returnValue(result) if __name__ == '__main__': import qt5reactor qt5reactor.install() from twisted.internet import reactor reactor.callWhenRunning(print_it) reactor.run()
Looks like the problem is that the twisted.internet.reactor is imported inside a block guarded by if __name__ == '__main__' When you import working_code that block doesn't run, because of the guard, so terrific_method tries to access "reactor" which doesn't exist. I guess your question is really how to get access to the reactor in working_code.py, since you can't import it in the top level namespace because you have ti install the qt5reactor *before* importing twisted.internet.reactor (right?). I don't know if there's a generally advised way of handling this, but I would simply put all the stuff in the guarded block in its own file and make sure to install the qt5reactor before importing anything else.
I think the "recommended" way to get access to a reactor instance is to pass it in to methods that require it. While this can sometimes seem tedious it a) helps testing (because now you can easily pass a fake reactor object like Clock or a Mock instance) and b) shows you (and your users) which methods are (or might-be) async. So, try a signature like "def terrific_method(reactor):" instead. Now when you're writing tests, you can do this: fake_reactor = Clock() d = terrific_method(fake_reactor) fake_reactor.advance(2) # etc. -- meejah
On Fri, 2016-07-29 at 23:11 +0400, meejah wrote:
I think the "recommended" way to get access to a reactor instance is to pass it in to methods that require it.
While this can sometimes seem tedious it a) helps testing (because now you can easily pass a fake reactor object like Clock or a Mock instance) and b) shows you (and your users) which methods are (or might-be) async.
So, try a signature like "def terrific_method(reactor):" instead. Now when you're writing tests, you can do this:
fake_reactor = Clock() d = terrific_method(fake_reactor) fake_reactor.advance(2) # etc.
Ah yes, you answered a question of mine not so long ago earlier and told me exactly that....sorry forgot. workig example if anybody ever digs this out: i modified the code like this: working_code.py from twisted.internet.defer import inlineCallbacks, Deferred, returnValue @inlineCallbacks def print_it(reactor): arg = yield terrific_method(reactor) print arg @inlineCallbacks def terrific_method(reactor): d = Deferred() reactor.callLater(2, d.callback, 2) result = yield d returnValue(result) if __name__ == '__main__': import qt5reactor qt5reactor.install() from twisted.internet import reactor reactor.callWhenRunning(print_it, reactor) reactor.run() main_code.py: import qt5reactor qt5reactor.install() from twisted.internet import reactor from working_code import print_it print_it(reactor) reactor.run() now on to some tests...
steven meier <commercials24@yahoo.de> writes:
if __name__ == '__main__': import qt5reactor qt5reactor.install() from twisted.internet import reactor reactor.callWhenRunning(print_it, reactor) reactor.run()
For "client-style" things (I guess I just mean "something that exits"), there's even a utility function that calls some method you provide with the reactor as the first argument, and arranges for reactor.stop() to get called exactly once (when the Deferred returned by your method fires). import qt5reactor qt5reactor.install() from twisted.internet.task import react if __name__ == '__main__': react(print_it) -- meejah
hi, after my last question which was answered with: ...the reactor should be passed in by the user... i ran into getPage(), the file: ./lib/python2.7/site-packages/twisted/web/client.py which contains getPage() imports the reactor at the top. it can be easily changed to add a argument to getPage() which passes it down to _makeGetter... then just comment out the import at the top and getPage() works when given a reactor as argument. probably breaking a lot of other code in that file. since getPage() is a method thats probably used a lot...did i understand the passing of the reactor or i did my mind go overboard? as a reminder: i want to use the qt5reactor to get some gui output
On Jul 30, 2016, at 5:03 AM, steven meier <commercials24@yahoo.de> wrote:
hi,
after my last question which was answered with: ...the reactor should be passed in by the user...
i ran into getPage(), the file: ./lib/python2.7/site-packages/twisted/web/client.py which contains getPage() imports the reactor at the top.
it can be easily changed to add a argument to getPage() which passes it down to _makeGetter... then just comment out the import at the top and getPage() works when given a reactor as argument.
probably breaking a lot of other code in that file.
since getPage() is a method thats probably used a lot...did i understand the passing of the reactor or i did my mind go overboard?
as a reminder: i want to use the qt5reactor to get some gui output
Don't use getPage. You want Agent.request <https://twistedmatrix.com/documents/16.3.0/api/twisted.web.client.Agent.html#request>, or possibly treq.get <http://treq.readthedocs.org>. getPage has a lot of problems and will be deprecated in a future release. -glyph
participants (4)
-
Daniel Sank
-
Glyph Lefkowitz
-
meejah
-
steven meier