Python - 将TCP套接字对象传递给多处理队列

Nic*_* K. 1 sockets python-2.7 python-multiprocessing

我有一个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
Run Code Online (Sandbox Code Playgroud)

我可以使用任何替代品吗?

mat*_*ata 7

multiprocessing.Queue从python3.4开始,通过一个正常工作发送一个套接字,因为从该版本a ForkingPickler用于序列化要放入队列的对象,并且该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()
Run Code Online (Sandbox Code Playgroud)

而不是直接发送套接字,然后需要发送其pickle版本并在消费者中取消它.简单的例子:

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()
Run Code Online (Sandbox Code Playgroud)

使插槽可选择只在多处理的上下文中有意义,将它写入文件并稍后使用或尝试在不同的PC上或在原始进程结束后使用它是没有意义的.因此,全局制作套接字可选(例如,通过使用copyreg机制)并不是一个好主意.

  • 这正是我要找的!这样,我可以将套接字传递给进程,并且它工作得很好!谢谢! (2认同)