【发布时间】:2017-04-19 14:15:21
【问题描述】:
此代码在 Linux 上运行良好,但在 Windows 下失败(这是预期的)。我知道多处理模块使用fork() 来生成一个新进程,因此父级(即打开的套接字)拥有的文件描述符由子级继承。但是,据我了解,您可以通过多处理发送的唯一数据类型需要是可腌制的。在 Windows 和 Linux 上,套接字对象是不可腌制的。
from socket import socket, AF_INET, SOCK_STREAM
import multiprocessing as mp
import pickle
sock = socket(AF_INET, SOCK_STREAM)
sock.connect(("www.python.org", 80))
sock.sendall(b"GET / HTTP/1.1\r\nHost: www.python.org\r\n\r\n")
try:
pickle.dumps(sock)
except TypeError:
print("sock is not pickleable")
def foo(obj):
print("Received: {}".format(type(obj)))
data, done = [], False
while not done:
tmp = obj.recv(1024)
done = len(tmp) < 1024
data.append(tmp)
data = b"".join(data)
print(data.decode())
proc = mp.Process(target=foo, args=(sock,))
proc.start()
proc.join()
我的问题是为什么 socket 对象,一个明显不可腌制的对象,可以通过多处理传递?它不像Windows那样使用pickle吗?
【问题讨论】:
-
文件描述符没有“发送”,它们就在那里。
-
什么意思?我可能(并且必须部分)错了,但我认为“args”参数中的任何内容都需要是可腌制的。不是这样吗?
-
参数没有被腌制,它们只是传递给子进程中的函数。只有在进程之间传输的对象需要被pickle。
-
谁来决定那是什么?操作系统大概。那么实际的socket对象本身并不是在进程之间发送的,而是维护了底层的文件描述符呢?我知道它是由孩子继承的,但我认为套接字对象也传递给了孩子,而不仅仅是简单的描述符。
-
不,套接字对象与进程内存映射的所有其他部分一样,已经存在在子进程中,因为分叉会产生几乎精确的父母的副本。
标签: python linux sockets python-multiprocessing