Функция Python Twisted deferToThread не работает должным образом - PullRequest
2 голосов
/ 26 ноября 2011

Моя цель здесь состоит в том, чтобы сделать простой сервер, обрабатывающий TCP-сообщение, такое как «process My String», которое отправляет «My String», для обработки с помощью достаточно длительной операции, называемой (здесь slowFunction).Здесь я вызываю эту функцию с помощью deferToThread, но, похоже, ничего не произошло: сообщения обратного вызова защищенного нигде не отображаются (точки останова показывают, что он никогда не вызывался), а печать в функции не отображается (точки останова показывают, что она никогда не вызывается)

from twisted import protocols
from twisted.protocols import basic
from twisted.internet import threads, protocol, reactor
from twisted.application import service, internet
import re
import time

def slowFunction(arg):
    print "starting process"
    time.sleep(1)
    print "processed "+arg

class MySimpleServer(basic.LineReceiver):

    PROCESS_COMMAND = "process (.*)" #re pattern
    processFunction = slowFunction
    clients = []

    def connectionMade(self):
        print "Client connected"
        MySimpleServer.clients.append(self)

    def connectionLost(self, reason):
        print "Client gone"
        MySimpleServer.clients.remove(self)

    def onProcessDone(self):
        self.message("Process done")

    def onError(self):
        self.message("Process fail with error")

    def lineReceived(self, line):
        processArgumentResult = re.search(MySimpleServer.PROCESS_COMMAND, line)
        if not processArgumentResult == None:
            processArgument = processArgumentResult.groups()[0] 
            deferred = threads.deferToThread(MySimpleServer.processFunction, processArgument)
            deferred.addCallback(self.onProcessDone)
            deferred.addErrback(self.onError)
            self.message("processing your request")
        else:
            print "Unknown message line: "+line

    def message(self, message):
        self.transport.write(message + '\n')

if __name__ == '__main__':
    factory = protocol.ServerFactory()
    factory.protocol = MySimpleServer
    factory.client = []

    reactor.listenTCP(8000, factory)
    reactor.run()

Ответы [ 2 ]

3 голосов
/ 26 ноября 2011

Другой способ сделать это можно с помощью staticmethod;это только законное использование для него.

class MySimpleServer(basic.LineReceiver):
    processFunction = staticmethod(slowFunction)
3 голосов
/ 26 ноября 2011

Мне помогли парни из twisted irc

Точки: обратный вызов (onProcessDone и onError) должен принимать аргумент результата, а функция вызываетсяby deferToThread получит self в качестве аргумента (это должен один из методов класса MySimpleServer).

Окончательный код теперь:

from twisted import protocols
from twisted.protocols import basic
from twisted.internet import threads, protocol, reactor
from twisted.application import service, internet
import re
import time

def slowFunction(arg):
    print "starting process"
    time.sleep(20)
    print "processed "+arg

class MySimpleServer(basic.LineReceiver):

    PROCESS_COMMAND = "process (.*)" #re pattern
    clients = []

    def connectionMade(self):
        print "Client connected"
        MySimpleServer.clients.append(self)

    def connectionLost(self, reason):
        print "Client gone"
        MySimpleServer.clients.remove(self)

    def onProcessDone(self, result):
        self.message("Process done")

    def onError(self, result):
        self.message("Process fail with error")

    def processFunction(self, processArgument):
        slowFunction(processArgument)

    def lineReceived(self, line):
        processArgumentResult = re.search(MySimpleServer.PROCESS_COMMAND, line)
        if not processArgumentResult == None:
            processArgument = processArgumentResult.groups()[0] 
            deferred = threads.deferToThread(self.processFunction, processArgument)
            deferred.addCallback(self.onProcessDone)
            deferred.addErrback(self.onError)
            self.message("processing your request")
        else:
            print "Unknown message line: "+line

    def message(self, message):
        self.transport.write(message + '\n')

if __name__ == '__main__':
    factory = protocol.ServerFactory()
    factory.protocol = MySimpleServer
    factory.client = []

    reactor.listenTCP(8000, factory)
    reactor.run()
...