In general, if you have to call reactor.stop() manually like this in a script, 
you're probably doing too much manual fiddling with its lifecycle.  I have not 
fully debugged this example, but I suspect it's just because the error is 
synchronous before the reactor starts.

However, rather than carefully managing the reactor's startup state like this 
where half your code runs synchronously before reactor startup, consider using 
<https://docs.twistedmatrix.com/en/stable/api/twisted.internet.task.html#react> 
instead and putting all your code (other than your imports) into your main 
function.  This will result in far fewer confusing scenarios.  Don't stop the 
reactor, just complete your coroutine and let `react()` shut it down for you 
when you're done.

All that said: there are probably a bunch of improvements to the API and 
documentation that could make this easier, and the reactor's starting/stopping 
state shouldn't be such an opaque mess.  It might be nice to eventually put it 
into an Automat state machine, for example, with some more explicit queries and 
fewer flags.  So it's not like there's no work to be done here.  But even if we 
did all that, the right way to write 99% of applications would still be to use 
something like a `twist` plugin, or a callable passed to `react`.

Hope this helps,

-g

> On Jan 22, 2025, at 1:45 AM, Kirill Miazine <k...@krot.org> wrote:
> 
> This has been driving me crazy for a while -- for some reason
> reactor.stop() in the _error errback in example below raises
> error.ReactorNotRunning. In order to stop the reactor, I have to do
> reactor.callWhenRunning(reactor.stop) (or I did reactor.callLater(0,
> ...) until I discovered callWhenRunning).
> 
> In the example, I bind to a low port to make sure error is triggered.
> 
> #!/usr/local/bin/python3
> 
> from twisted.internet import reactor, defer, protocol
> from twisted.internet.protocol import Factory
> from twisted.internet.endpoints import TCP4ServerEndpoint
> 
> def _port(port):
>    print('got', port)
> 
> def _error(err):
>    print('got err', err)
>    print('is reactor running?', reactor.running)
>    print('is reactor running?', (lambda: reactor.running)())
>    reactor.stop()
> #    reactor.callWhenRunning(reactor.stop)
> 
> d = TCP4ServerEndpoint(reactor, 123).listen(Factory())
> d.addCallback(_port)
> d.addErrback(_error)
> d.addErrback(print)
> 
> reactor.run()
> 
> 
> OTOH, in the following example reactor.stop() is stoppig the reactor
> properly:
> 
> #!/usr/local/bin/python3
> 
> from twisted.internet import reactor, defer
> 
> def cb(res):
>    print('running?', reactor.running)
>    if res == 'bar':
>        raise Exception()
>    reactor.stop()
> 
> def eb(err):
>    print('running?', reactor.running)
>    print(err)
>    reactor.stop()
> 
> d = defer.Deferred()
> d.addCallback(cb)
> d.addErrback(eb)
> 
> #reactor.callWhenRunning(d.callback, 'foo')
> reactor.callWhenRunning(d.callback, 'bar')
> 
> reactor.run()
> 
> 
> Any ideas?
> _______________________________________________
> Twisted mailing list -- twisted@python.org
> To unsubscribe send an email to twisted-le...@python.org
> https://mail.python.org/mailman3/lists/twisted.python.org/
> Message archived at 
> https://mail.python.org/archives/list/twisted@python.org/message/XK6XURKCRX44TLIY4C3RT3HZV5WYDA6C/
> Code of Conduct: https://twisted.org/conduct

_______________________________________________
Twisted mailing list -- twisted@python.org
To unsubscribe send an email to twisted-le...@python.org
https://mail.python.org/mailman3/lists/twisted.python.org/
Message archived at 
https://mail.python.org/archives/list/twisted@python.org/message/STR3ACUM4LPUQBVNNSGVUEU3PDLADDW7/
Code of Conduct: https://twisted.org/conduct

Reply via email to