Многопоточный XML-RPC (python3.7.1)

Сервер:

  import time                                                                   
  import random                                                                 
  from threading import Thread                                                  
  from xmlrpc.server import SimpleXMLRPCServer                                  

  class ServerThread(Thread):                                                   
      def __init__(self, server_addr):                                          
      ┆   Thread.__init__(self)                                                 
      ┆   self.server = SimpleXMLRPCServer(server_addr)                         
      ┆   self.server.register_function(sleep, 'sleep')                         

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

  # sleep for random number of seconds                                          
  def sleep():                                                                  
      r = random.randint(2,10)                                                  
      print('sleeping {} seconds'.format(r))                                    
      time.sleep(r)                                                             
      return 'slept {} seconds, exiting'.format(r)                              

  # run server                                                                  
  def run_server(host = "localhost", port=8000):                                  
      server_addr = (host, port)                                                
      thread1 = ServerThread(server_addr)                                       
      thread1.start()                                                           
      print("Server thread started. Testing server ...")                        
      print('listening on {} port {}'.format(host, port))                       

  if __name__ == '__main__':                                                    
     run_server()

Клиент:

import xmlrpc.client

server = xmlrpc.client.ServerProxy("http://localhost:8000/", allow_none=True)

print(server.sleep())
print(server.sleep())
print(server.sleep())
print(server.sleep())

Вопрос:

Я не могу создать несколько экземпляров ServerThread, которые слушают один и тот же порт, выдает исключение.

Я хотел бы, чтобы все 4 потока выполнялись параллельно.

Что мне не хватает? После этого следует лекция по GIL?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
1 970
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема, которую вы обнаружили, заключается в том, что прослушивание определенного порта возможно только один раз. Это означает, что вместо запуска нескольких потоков для прослушивания вам необходимо иметь одного прослушивателя, который делегирует ответ разным потокам.

Python предоставляет готовый многопоточный сервер, который можно использовать в сочетании со встроенными серверными классами, такими как SimpleXMLRPCServer.

В следующем коде реализован многопоточный спящий сервер, а ниже показан многопоточный клиент и выходные данные, отмечен разный порядок времени ожидания между сервером и клиентом.

Многопоточный сервер:

import random
import time
from socketserver import ThreadingMixIn
from xmlrpc.server import SimpleXMLRPCServer


class SimpleThreadedXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):
    pass


# sleep for random number of seconds
def sleep():
    r = random.randint(2, 10)
    print('sleeping {} seconds'.format(r))
    time.sleep(r)
    return 'slept {} seconds, exiting'.format(r)


# run server
def run_server(host = "localhost", port=8000):
    server_addr = (host, port)
    server = SimpleThreadedXMLRPCServer(server_addr)
    server.register_function(sleep, 'sleep')

    print("Server thread started. Testing server ...")
    print('listening on {} port {}'.format(host, port))

    server.serve_forever()


if __name__ == '__main__':
    run_server()

Многопоточный клиент:

import xmlrpc.client
from concurrent.futures import ThreadPoolExecutor, as_completed

def submit_sleep():
   server = xmlrpc.client.ServerProxy("http://localhost:8000/", allow_none=True)
   return server.sleep()

with ThreadPoolExecutor() as executor:
    sleeps = {executor.submit(submit_sleep) for _ in range(4)}
    for future in as_completed(sleeps):
        sleep_time = future.result()
        print(sleep_time)

Выход сервера:

Server thread started. Testing server ...
listening on localhost port 8000
sleeping 3 seconds
sleeping 9 seconds
sleeping 3 seconds
sleeping 10 seconds
127.0.0.1 - - [05/Dec/2018 14:32:02] "POST / HTTP/1.1" 200 -
127.0.0.1 - - [05/Dec/2018 14:32:02] "POST / HTTP/1.1" 200 -
127.0.0.1 - - [05/Dec/2018 14:32:08] "POST / HTTP/1.1" 200 -
127.0.0.1 - - [05/Dec/2018 14:32:09] "POST / HTTP/1.1" 200 -

Вывод клиента:

slept 3 seconds, exiting
slept 3 seconds, exiting
slept 9 seconds, exiting
slept 10 seconds, exiting

Другие вопросы по теме

Похожие вопросы

Общие советы по созданию "стандартных" компонентов на нескольких языках
Python: найти разделы из текстового файла с помощью обратного цикла
Как отобразить числа из первого столбца и посчитать количество происшествий?
Сравнение интервалов с датами / часами на указателе даты и времени (проверка, находится ли час между двумя периодами)
Объединить список на основе общих ценностей
Как организовать список кортежей так, чтобы кортеж, связанный с наивысшим значением по сравнению с другим кортежом, был удален и возвращал максимальное значение
Условно со значением из определенной ячейки в Excel
Python Pandas NLTK: отображение частоты общих фраз (ngrams) из текстового поля во фрейме данных с помощью BigramCollocationFinder
Для каждого столбца и ячейки в фрейме данных заполните NaN / Null случайным значением из этого столбца
Как использовать MultiCursor на графике Pandas