Ethan
Ethan

Reputation: 747

How to Process Data outside of Twisted thread

I am trying to write a UDP listener that performs an API call in response, but based on the data contained within the received UDP datagram. It appears callMultipleInThreads runs both functions in a single thread. Upon receiving a UDP datagram, I was hoping functionOne would end as functionTwo starts in a new thread (to do the API call) This does not appear to be the case.

import time
from twisted.internet import reactor, threads

def functionOne(x):
    print x

def functionTwo(x):
    time.sleep(10)
    print x

commands = [(functionOne, ["First Function"], {})]
commands.append((functionTwo, ["Second Function"], {}))
reactor.listenUDP(9999, threads.callMultipleInThread(commands))
reactor.run()

I am new to writing threading code. How could better allow a second function not block functionOne from closing? Would forking the API call in funtionTwo be a better method?

Upvotes: 2

Views: 494

Answers (1)

Shyba
Shyba

Reputation: 33

As documentation explains, threads.callMultipleInThread will run your functions on one thread, so they can still block each other. If I understood your goal, you should defer functionTwo to it's own new thread instead of sharing the same one as functionOne. There is a quick section on how to integrate blocking calls with Twisted and this is using deferToThread on the blocking call.

The last missing thing I noticed was a Protocol implementation. So, I will show a quick snippet to demonstrate how to run functionTwo on a new thread while listening for UDP:

import time                                                                                                                                                                                                  
from twisted.internet import reactor, threads                                                                                                                                                                
from twisted.internet.protocol import DatagramProtocol                                                                                                                                                       


class DoNotBlockMeProtocol(DatagramProtocol):                                                                                                                                                                
    def datagramReceived(self, data, (host, port)):                                                                                                                                                          
        reactor.callLater(0, functionOne, "First Function")                                                                                                                                                  
        threads.deferToThread(functionTwo, "Second Function")                                                                                                                                                
        print "received %r from %s:%d" % (data, host, port)                                                                                                                                                          self.transport.write(data, (host, port))                                                                                                                                                             


def functionOne(x):                                                                                                                                                                                          
    print x                                                                                                                                                                                                  


def functionTwo(x):                                                                                                                                                                                          
    time.sleep(10)                                                                                                                                                                                           
    print x                                                                                                                                                                                                  

reactor.listenUDP(9999, DoNotBlockMeProtocol())                                                                                                                                                              
reactor.run()

In order to see it working, run this on a linux shell:

$ echo -n “foo” | nc -4u -w1 localhost 9999

You can also learn more about using UDP on this guide: https://twistedmatrix.com/documents/current/core/howto/udp.html

Upvotes: 1

Related Questions