Сервер:
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 предоставляет готовый многопоточный сервер, который можно использовать в сочетании со встроенными серверными классами, такими как 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