2009-02-02 13 views
2

J'ai une classe que je souhaite tester via SimpleXMLRPCServer en python. La façon dont mon test d'unité est configuré est que je crée un nouveau thread, et démarre SimpleXMLRPCServer dans cela. Ensuite, je cours tout le test, et finalement fermé.Exécution de SimpleXMLRPCServer dans un thread séparé et fermeture

Ceci est mon ServerThread:

class ServerThread(Thread): 
    running = True 
    def run(self): 
     self.server = #Creates and starts SimpleXMLRPCServer 

     while (self.running): 
      self.server.handle_request() 

    def stop(self): 
     self.running = False 
     self.server.server_close() 

Le problème est, que l'appel ServerThread.stop(), suivie Thread.stop() et Thread.join() ne causera pas le fil pour arrêter correctement si il attend déjà une requête dans handle_request. Et comme il ne semble pas y avoir de mécanismes d'interruption ou de délai d'attente que je puisse utiliser, je ne sais pas comment je peux fermer le thread du serveur.

Répondre

1

Deux suggestions.

Suggestion L'une consiste à utiliser un processus séparé au lieu d'un thread séparé.

  • Créer un programme serveur XMLRPC autonome.

  • Commencez par subprocess.Popen().

  • Tuez-le lorsque le test est terminé. Dans les systèmes d'exploitation standard (pas Windows), la destruction fonctionne bien. Dans Windows, cependant, il n'y a pas de fonction de destruction triviale, mais il existe des recettes pour cela.

L'autre suggestion est d'avoir une fonction dans votre serveur XMLRPC qui provoque l'auto-destruction du serveur. Vous définissez une fonction qui appelle sys.exit() ou os.abort() ou déclenche une exception similaire qui arrêtera le processus.

+0

Je garderai cette méthode en tête pour le futur. Je préfère les solutions multiplateformes donc la méthode d'arrêt semble la plus raisonnable. Je l'ai corrigé en envoyant une requête fictive qui terminera le thread comme self.running sera faux. – Staale

+0

Un sous-processus est multi-plateforme. Un sous-processus PLUS la méthode d'auto-destruction fonctionne le mieux. –

3

J'ai eu le même problème et après les heures de recherche je l'ai résolu en passant d'utiliser mon propre handle_request() boucle à serve_forever() pour démarrer le serveur.

serve_forever() démarre une boucle interne comme la vôtre. Cette boucle peut être arrêtée en appelant shutdown(). Après l'arrêt de la boucle, il est possible d'arrêter le serveur avec server_close().

Je ne sais pas pourquoi cela fonctionne et la handle_request() boucle ne le font pas, mais il ne; P

Voici mon code:

from threading import Thread 
from xmlrpc.server import SimpleXMLRPCServer 
from pyWebService.server.service.WebServiceRequestHandler import WebServiceRquestHandler 

class WebServiceServer(Thread): 
    def __init__(self, ip, port): 
     super(WebServiceServer, self).__init__() 
     self.running = True 
     self.server = SimpleXMLRPCServer((ip, port),requestHandler=WebServiceRquestHandler) 
    self.server.register_introspection_functions() 

    def register_function(self, function): 
     self.server.register_function(function) 

    def run(self): 
     self.server.serve_forever() 

    def stop_server(self): 
     self.server.shutdown() 
     self.server.server_close() 

print("starting server") 
webService = WebServiceServer("localhost", 8010) 
webService.start() 
print("stopping server") 
webService.stop_server() 
webService.join() 
print("server stopped") 
+0

Mise à jour (python 2.7.9): J'ai essayé ceci, et il n'était pas nécessaire d'importer 'WebServiceRequestHandler' (ou de fournir le gestionnaire' requestHandler'). – Jamie