[Twisted-Python] How to exit a twistd program with a status code ?

Hi, I have a program run through twistd, and would like to exit with a non zero status code on some error. I have a callback which stops the reactor and then sys.exit(some_value), but twistd still seems to catch the SystemExit exception after calling for reactor.stop(): Unhandled error in Deferred: Traceback (most recent call last): File "/home/david/local/lib/python2.6/site-packages/twisted/internet/base.py", line 1031, in connectionFailed self.factory.clientConnectionFailed(self, reason) File "/home/david/local/lib/python2.6/site-packages/twisted/web/client.py", line 350, in clientConnectionFailed self.deferred.errback(reason) File "/home/david/local/lib/python2.6/site-packages/twisted/internet/defer.py", line 307, in errback self._startRunCallbacks(fail) File "/home/david/local/lib/python2.6/site-packages/twisted/internet/defer.py", line 354, in _startRunCallbacks self._runCallbacks() --- <exception caught here> --- File "/home/david/local/lib/python2.6/site-packages/twisted/internet/defer.py", line 371, in _runCallbacks self.result = callback(self.result, *args, **kw) File "scripts/tests/run_tests.py", line 69, in exit_on_error sys.exit(1) exceptions.SystemExit: 1 What's the correct way of doing this ? cheers, David

I think that you should not put the sys.exit(1) call, after the reactor.stop() call.
From my very limited understanding of how Twisted reactor works, it could be done with something like:
statusCode = 1 #or whatever reactor.stop() in the method that stops the reactor and the exit call should be added where (after) the reactor is started: reactor.run() # this will be executed after reactor stops sys.exit(statusCode) Please, correct me if I write nonsense here. Pandelis Theodosiou On Fri, Sep 24, 2010 at 4:49 AM, David Cournapeau <cournape@gmail.com>wrote:

On 11:09 am, ypercube@gmail.com wrote:
Your understanding seems correct to me. :) This is basically how the feature would be implemented. Since David is using `twistd` though, he doesn't get to put extra code after the `reactor.run()` call. http://twistedmatrix.com/trac/ticket/2182 is a ticket for adding a feature to `twistd` to make this easier. Jean-Paul

I'd like to add my two cents here; maybe this may be valuable to someone. I might suggest, if reasonable, to allow for running the app with or without twistd. twistd is really handy for profiling/debugging/daemonizing/etc., but it does lack in other areas such as command line args and (new to me) return codes. The last few apps I've done, I've set up a standard Python entry point like: #!/usr/bin/env python from twisted.internet import reactor from myapp import main if __name__ == "__main__": # For quick/easy logging when running undaemonized log.startLogging(sys.stdout) reactor.callWhenRunning(main) reactor.run() Along with something for creating the application object in .tac files: from twisted.application.service import Application from twisted.internet import reactor from twisted.python.syslog import SyslogObserver from myapp import main def create_application(): app = Application("foo") # More robust logging for daemonized (production) mode observer = SyslogObserver("bar") app.setComponent(ILogObserver, observer.emit) reactor.callWhenRunning(main) return app And then, you end up with possibly a really simple .tac file: import myapp.tacapp application = myapp.tacapp.create_application() That seems to give the best of both worlds from what I've seen. Haven't seen any key drawbacks yet. - Paul Goins

David Cournapeau wrote:
This isn't a good answer, exactly, but it may do the trick... import os reactor.addSystemEventTrigger('after', 'shutdown', os._exit, some_value) reactor.stop() I'm not sure that controlling the process exit value really fits nicely with twistd's purpose, though. -Andrew.

I think that you should not put the sys.exit(1) call, after the reactor.stop() call.
From my very limited understanding of how Twisted reactor works, it could be done with something like:
statusCode = 1 #or whatever reactor.stop() in the method that stops the reactor and the exit call should be added where (after) the reactor is started: reactor.run() # this will be executed after reactor stops sys.exit(statusCode) Please, correct me if I write nonsense here. Pandelis Theodosiou On Fri, Sep 24, 2010 at 4:49 AM, David Cournapeau <cournape@gmail.com>wrote:

On 11:09 am, ypercube@gmail.com wrote:
Your understanding seems correct to me. :) This is basically how the feature would be implemented. Since David is using `twistd` though, he doesn't get to put extra code after the `reactor.run()` call. http://twistedmatrix.com/trac/ticket/2182 is a ticket for adding a feature to `twistd` to make this easier. Jean-Paul

I'd like to add my two cents here; maybe this may be valuable to someone. I might suggest, if reasonable, to allow for running the app with or without twistd. twistd is really handy for profiling/debugging/daemonizing/etc., but it does lack in other areas such as command line args and (new to me) return codes. The last few apps I've done, I've set up a standard Python entry point like: #!/usr/bin/env python from twisted.internet import reactor from myapp import main if __name__ == "__main__": # For quick/easy logging when running undaemonized log.startLogging(sys.stdout) reactor.callWhenRunning(main) reactor.run() Along with something for creating the application object in .tac files: from twisted.application.service import Application from twisted.internet import reactor from twisted.python.syslog import SyslogObserver from myapp import main def create_application(): app = Application("foo") # More robust logging for daemonized (production) mode observer = SyslogObserver("bar") app.setComponent(ILogObserver, observer.emit) reactor.callWhenRunning(main) return app And then, you end up with possibly a really simple .tac file: import myapp.tacapp application = myapp.tacapp.create_application() That seems to give the best of both worlds from what I've seen. Haven't seen any key drawbacks yet. - Paul Goins

David Cournapeau wrote:
This isn't a good answer, exactly, but it may do the trick... import os reactor.addSystemEventTrigger('after', 'shutdown', os._exit, some_value) reactor.stop() I'm not sure that controlling the process exit value really fits nicely with twistd's purpose, though. -Andrew.
participants (5)
-
Andrew Bennetts
-
David Cournapeau
-
exarkun@twistedmatrix.com
-
Pantelis Theodosiou
-
Paul Goins