Python 3 concurrent.futures Socket 服务器在 ThreadPoolExecutor 中可用,但在 ProcessPoolExecutor 中不可用

2 投票
2 回答
3602 浏览
提问于 2025-04-17 03:04

我正在尝试使用新的 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

你确定不是因为在运行 'executor.submit(...)' 之后调用了 'conn.close()' 吗?我只是把那一行去掉,然后在 mac10.12.6 和 python 3.6.3 上试了一下,结果很好。

0

说得好,Donkopotamus,你应该把这个当作答案发出来。

我把处理程序放在了一个尝试块里,当它试图调用 conn.recv() 时,我遇到了一个错误:[Errno 10038] 尝试在一个不是套接字的东西上进行操作。由于工作进程死掉得很惨,它出现了死锁。现在有了这个尝试块来捕捉错误,我可以继续连接,想连接多少就连接多少,而不会再出现死锁的问题。

如果我把代码改成使用 ThreadPoolExecutor,我就不会遇到这个错误。我尝试了几种方法,发现用 ProcessPoolExecutor 传递套接字给工作进程似乎没有正确的方法。我在网上找到了其他相关的信息,他们说在某些平台上可以做到,但在其他平台上不行。我在 Windows、Linux 和 MacOS X 上都试过了,结果在这些系统上都不行。这似乎是一个很大的限制。

撰写回答