0

After working through some of the basic tutorials, I want my TCP/UDP client to exit with a code indicating whether it connected or not. The right way to return an exit code in Twisted is:

point = TCP4ClientEndpoint(reactor, "localhost", 1234)
d = connectProtocol(point, ClientProtocol())
reactor.run()
sys.exit(0)

Then, when the process terminates, it will exit with code 0 to indicate a normal termination. If the client instead times out instead of successfully connecting, how should it pass a value back to that can then be passed to sys.exit instead of the constant 0?

ceridwen
  • 550
  • 2
  • 5
  • 14

1 Answers1

2

Determining whether the TCP connection succeeded or failed is accomplished by attending to the result of the Deferred:

d = connectProtocol(point, ClientProtocol())
d.addCallbacks(
    connected,
    did_not_connect,
)

With appropriate implementations of connected and did_not_connect, you should be able to pass a suitable value to a subsequent sys.exit call.

For example,

class Main(object):
    result = 1

    def connected(self, passthrough):
        self.result = 0
        return passthrough

    def did_not_connect(self, passthrough):
        self.result = 2
        return passthrough

    def exit(self):
        sys.exit(self.result)

main = Main()
d = connectProtocol(point, ClientProtocol())
d.addCallbacks(
    main.connected,
    main.did_not_connect,
)
reactor.run()
main.exit()
Jean-Paul Calderone
  • 47,755
  • 6
  • 94
  • 122
  • Because I need to support UDP too, I couldn't use callbacks (AFAICT, listenUDP doesn't return a Deferred instance), so I had to take a slightly different approach that's morally the same: add the twisted.protocols.policies.TimeoutMixin to the protocol classes, set an instance variable in timeoutConnection(), and read the instance variable in the sys.exit() call. This unfortunately involves what I was hoping to avoid, using a global instance to pass state set in non-`__init__` methods, but it doesn't seem like there's another way to do it. – ceridwen Oct 02 '17 at 19:27
  • UDP clients don't meaningfully fail to connect. listenUDP succeeds synchronously. Regardless, the same approach as I outlined in this answer can be used to avoid global state elsewhere as well. – Jean-Paul Calderone Oct 02 '17 at 22:56