【问题标题】:Python - Passing a TCP socket object to a multiprocessing QueuePython - 将 TCP 套接字对象传递给多处理队列
【发布时间】:2016-07-22 02:38:20
【问题描述】:

我有一个 TCP 服务器和客户端。在服务器脚本的某个时刻,我启动了一个进程,该进程需要能够获取每个新连接并向其发送数据。为此,我有一个multiprocessing.Queue(),我想将来自主进程的每个新连接放入其中,以便我打开的进程可以从中获取连接并向它们发送数据。但是,您似乎无法将任何您想要的东西传递给队列。当我尝试传递连接(一个套接字对象)时,我得到:

Traceback (most recent call last):
  File "/usr/lib/python2.7/multiprocessing/queues.py", line 266, in _feed
    send(obj)
TypeError: expected string or Unicode object, NoneType found

我可以使用任何替代方案吗?

【问题讨论】:

  • 你不能那样做。 Queue 旨在发送 Python 对象,而套接字涉及特定于操作系统的数据(例如套接字 fd),因此它们不能简单地传递给子进程。
  • 好吧,我找到了解决这个问题的方法。但是,我真的很想看到一种真正做到这一点的方法,即使你说这是不可能的。

标签: python-2.7 sockets python-multiprocessing


【解决方案1】:

从 python3.4 开始,通过multiprocessing.Queue 发送套接字可以正常工作,因为从那个版本开始,ForkingPickler is used 可以序列化要放入队列中的对象,并且pickler 知道如何序列化套接字和其他包含文件句柄。

multiprocessing.reduction.ForkingPickler 类确实已经存在于 python2.7 中并且可以腌制套接字,只是 multiprocessing.Queue 没有使用它。

如果您无法切换到 python3.4+ 并且确实需要 python2.7 中的类似功能,则解决方法是创建一个使用 ForkingPickler 序列化对象的函数,例如:

from multiprocessing.reduction import ForkingPickler
import StringIO

def forking_dumps(obj):
    buf = StringIO.StringIO()
    ForkingPickler(buf).dump(obj)
    return buf.getvalue()

您需要发送其腌制版本并在消费者中取消腌制,而不是直接发送套接字。简单例子:

from multiprocessing import Queue, Process
from socket import socket
import pickle

def handle(q):
    sock = pickle.loads(q.get())
    print 'rest:', sock.recv(2048)

if __name__ == '__main__':
    sock = socket()
    sock.connect(('httpbin.org', 80))
    sock.send(b'GET /get\r\n')
    # first bytes read in parent
    print 'first part:', sock.recv(50)

    q = Queue()
    proc = Process(target=handle, args=(q,))
    proc.start()
    # use the function from above to serialize socket
    q.put(forking_dumps(sock))
    proc.join()

使套接字可腌制仅在多处理上下文中才有意义,将其写入文件并稍后使用或尝试在不同的电脑上或在原始进程结束后使用它是没有意义的。因此,让套接字在全局范围内可腌制并不是一个好主意(例如,通过使用 copyreg 机制)。

【讨论】:

  • 这正是我想要的!这样,我可以将套接字传递给进程并且它工作得很好!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-12
  • 2018-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-08
相关资源
最近更新 更多