Сервер сокетов Python 3 concurrent.futures работает с ThreadPoolExecutor, но не с ProcessPoolExecutor - PullRequest
0 голосов
/ 26 сентября 2011

Я пытаюсь создать простой сервер сокетов, используя новые классы concurrent.futures. Я могу заставить его работать нормально с ThreadPoolExecutor, но он просто зависает, когда я использую ProcessPoolExecutor, и я не могу понять, почему. Учитывая обстоятельства, я подумал, что это может иметь какое-то отношение к попытке передать что-то в дочерний процесс, который не может быть засолен, но я так не думаю. Упрощенная версия моего кода приведена ниже. Буду признателен за любой совет.

import concurrent.futures
import socket, os

HOST = ''
PORT = 9001

def request_handler(conn, addr):
    pid = os.getpid()
    print('PID', pid, 'handling connection from', addr)
    while True:
        data = conn.recv(1024)
        if not data:
            print('PID', pid, 'end connection')
            break
        print('PID', pid, 'received:', bytes.decode(data))
        conn.send(data)
    conn.close()

def main():
    with concurrent.futures.ProcessPoolExecutor(max_workers=4) as executor:
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
            sock.bind((HOST, PORT))
            sock.listen(10)
            print("Server listening on port", PORT)
            while True:
                conn, addr = sock.accept()
                executor.submit(request_handler, conn, addr)
                conn.close()
            print("Server shutting down")


if __name__ == '__main__':
    main()

Ответы [ 2 ]

0 голосов
/ 16 декабря 2017

вы уверены, что это не вызвано 'conn.close ()' после запуска executor.submit (...) '?Я просто удаляю строку и пробую на mac10.12.6 и python 3.6.3, он работает хорошо.

0 голосов
/ 26 сентября 2011

Хорошо, позвони Донкопотамусу, ты должен был опубликовать это как ответ.

Я завернул обработчик в блок try, и когда он пытается вызвать conn.recv (), я получил исключение: [Errno 10038] Была предпринята попытка выполнить операцию с чем-то, что не является сокетом. Поскольку рабочий процесс умирал плохо, он зашел в тупик. С блоком try, фиксирующим ошибку, я могу продолжать подключаться столько, сколько я хочу, без какой-либо тупика.

Я не получаю эту ошибку, если я изменяю код для использования ThreadPoolExecutor. Я пробовал несколько вариантов, и похоже, что нет способа правильно передать сокет рабочему процессу в ProcessPoolExecutor. Я нашел другие ссылки на это в Интернете, но они говорят, что это может быть сделано на некоторых платформах, но не на других. Я пробовал это на Windows, Linux и MacOS X, и он не работает ни на одном из них. Это кажется существенным ограничением.

...