Python thread started but stuck because of twisted reactor in other thread (possibly)

51 Views Asked by At

Trying to make an API based on twisted work (https://github.com/spotware/OpenApiPy)

Here is some incomplete code that starts a twisted reactor:

def onError(failure):
    print("Message Error: ", failure)

def connected(client):
    print("\nConnected")
    request = ProtoOAApplicationAuthReq()
    request.clientId = app_id
    request.clientSecret = app_secret
    deferred = client.send(request)
    deferred.addErrback(onError)

def disconnected(client, reason): # Callback for client disconnection
    print("\nDisconnected: ", reason)

def onMessageReceived(client, message): # Callback for receiving all messages
    print("Message received: \n", Protobuf.extract(message))

def send_messages():
    print('waiting for messages to send')
    while True:
        print(1)
        message = message_queue.get()

        deferred = client.send(message)
        deferred.addErrback(onError)
        time.sleep(10)

def send_message_thread(message):
    message_queue.put(message)

def main():
    client.setConnectedCallback(connected)
    client.setDisconnectedCallback(disconnected)
    client.setMessageReceivedCallback(onMessageReceived)
    client.startService()

    # send_messages()
    send_thread = threading.Thread(target=send_messages)
    send_thread.daemon = True  # The thread will exit when the main program exits
    send_thread.start()

    # Run Twisted reactor
    reactor.run()

if __name__ == "__main__":
    main()

It connects successfully and this is the output:

waiting for messages to send
1

Connected
Message received:
Message received:
Message received:
Message received:
...

So it looks like the send_thread is started but then the while True is actually executed just once - does anybody know why? (I guess it is blocked by reactor.run() yet Im not familiar with this twisted stuff)

If the send_thread was running I guess there should be more 1 printed out

1

There are 1 best solutions below

0
Jean-Paul Calderone On

You left out the definition of client but from the names used related to it (deferred, addErrback) I'm going to guess it is an interface to some code that uses some Twisted APIs.

Almost all Twisted APIs must be used in the thread in which the reactor is running. If an API is safe for use in a different thread it will be clearly marked as such.

The behavior of Twisted APIs when called from a non-reactor thread is unspecified.

If you you have code running in a different thread and you want to use some piece of Twisted functionality from it, you can use reactor.callFromThread or blockingCallFromThread.