2

新しい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()
4

2 に答える 2

0

Donkopotamusに電話してください、あなたは答えとしてそれを投稿するべきでした。

ハンドラーをtry-blockでラップし、conn.recv()を呼び出そうとすると、例外が発生しました。[Errno10038]ソケットではないもので操作が試行されました。ワーカープロセスがひどく死んでいたので、それは行き詰まりました。try-blockを設定してエラーをキャッチすると、デッドロックなしで好きなだけ接続を続けることができます。

ThreadPoolExecutorを使用するようにコードを変更しても、このエラーは発生しません。いくつかのオプションを試しましたが、ProcessPoolExecutorのワーカープロセスにソケットを適切に渡す方法がないようです。私はインターネットでこれに関する他の言及を見つけましたが、彼らはそれがいくつかのプラットフォームでできるが他のプラットフォームではできないと言っています。Windows、Linux、MacOS Xで試しましたが、いずれも動作しません。これは重大な制限のようです。

于 2011-09-26T17:49:04.403 に答える
0

'executor.submit(...)'を実行した後、'conn.close()'が原因ではないことを確認しますか?行を削除して、mac10.12.6とpython3.6.3で試してみます。

于 2017-12-16T15:53:38.073 に答える