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

Python 2.7 Python-将TCP套接字对象传递到多处理队列,python-2.7,sockets,python-multiprocessing,Python 2.7,Sockets,Python Multiprocessing,我有一个TCP服务器和客户端。在服务器脚本中的某个时刻,我启动了一个进程,该进程需要能够获取每个新连接并向其发送数据。为了做到这一点,我有一个多处理.Queue(),我想把主进程的每个新连接都放到这个队列中,这样我打开的进程就可以从主进程中获取连接并向它们发送数据。但是,您似乎无法将任何想要传递给队列的内容。当我尝试传递连接(套接字对象)时,我得到: 我可以使用其他方法吗?通过多处理发送套接字。从python3.4开始,队列可以很好地工作,因为从该版本开始,pickler可以序列化要放入队列的对

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


我可以使用其他方法吗?

通过
多处理发送套接字。从python3.4开始,队列可以很好地工作,因为从该版本开始,pickler可以序列化要放入队列的对象,并且pickler知道如何序列化套接字和包含文件句柄的其他对象

该类在python2.7中已经存在,并且可以pickle套接字,
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()
然后,您需要发送其pickle版本并在使用者中取消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()

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

您不能这样做<代码>队列
用于发送Python对象,而套接字涉及操作系统特定的数据(例如套接字fd),因此它们不能简单地传递给子进程。我找到了解决此问题的方法。然而,我真的很有兴趣看到一种真正做到这一点的方法,即使你说这是不可能的。这正是我想要的!通过这种方式,我可以将套接字传递给进程,它工作得很好!谢谢
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()