Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 是否复制管道连接?_Python_Multiprocessing - Fatal编程技术网

Python 是否复制管道连接?

Python 是否复制管道连接?,python,multiprocessing,Python,Multiprocessing,在Python多处理中,我看到一些代码执行以下操作 def worker(parent_conn, child_conn): parent_conn.close() while True: x = child_conn.recv() if x == 'close': child_conn.close() break else: do something #

在Python多处理中,我看到一些代码执行以下操作

def worker(parent_conn, child_conn):
    parent_conn.close()

    while True:
        x = child_conn.recv()

        if x == 'close':
            child_conn.close()
            break
        else:
            do something

# Following as master

parent_conn, child_conn = Pipe()
process = Process(target=worker, args=[parent_conn, child_conn])

process.start()

child_conn.close()  # not used

for _ in range(10):
    parent_conn.send(something)
    parent_conn.recv()

parent_conn.send('close')

process.join()
我的问题是

  • 为什么在worker中,我们可以直接关闭父连接,它应该已经断开了管道。那么,进程分叉(deepcopy)是否同时包含工作进程的父连接和子连接

  • 为什么同样在主程序中,我们也可以直接关闭子连接,原因与上述问题相同

  • 如果我没有从父连接向worker发送
    'close'
    ,那么即使我在主程序中加入了进程,worker while循环似乎也会无限运行

  • 创建两个连接,它们传播到子流程的方式取决于所用操作系统的实现

    在*nix系统上,
    fork()
    用于生成一个新进程,该进程从父进程继承所有打开的文件描述符。最好的做法是立即关闭分叉后不需要的所有继承的文件描述符,这就是这里要做的。在没有
    fork()
    (windows)的系统上,这就没有什么意义了,因为在windows中,连接的实现方式不同,但仍然有效

    父节点和辅助节点都会关闭它们不使用的连接的一端。由于它们是独立的进程,在父进程中调用
    child\u conn.close()
    对辅助进程中的
    child\u conn
    没有影响,它只关闭连接的一端,另一端仍可使用。因此,工作者可以调用
    client\u-conn
    上的
    recv()
    ,使用
    parent\u-conn.send()
    将对象发送到父对象中,反之亦然

    您的示例实际上不起作用,因为在连接关闭后,在主进程中有一个对
    child\u conn.recv()
    的调用。这将引发一个异常

    process.join()
    等待进程完成,这只有在循环结束时才会执行,因此如果您从未发送
    'close'
    消息,woker将无限期阻止
    child\u conn.recv()
    ,并且
    join()
    将永远不会返回。这是一个典型的死锁


    另一种向工作人员发出退出信号的方式是调用
    parent\u conn.close()
    ,而不是发送关闭消息。这将导致
    child\u conn.recv()
    引发EOF错误,但前提是所有进程(包括工作进程)都已关闭基础文件描述符,这也是通常关闭不需要的文件描述符的原因之一。

    感谢您的详细回答。只是为了确保我是否正确使用它,例如在Ubuntu中,
    fork()
    会复制管道吗?i、 e.在父进程中,有管道的两端,而在辅助进程中,它有一个两端都被复制的独立版本?顺便说一句,如果上面是正确的,那么在主辅助进程模式中,是否更建议只使用
    args=child\u conn
    而不是
    args=[parent\u conn,child\u conn]创建辅助进程
    由于工作进程并不真正使用复制的
    父连接
    进程在
    fork()上继承打开的文件描述符
    在任何情况下,在pickle/unpickle时作为agment传递的连接对象基本上只告诉进程在创建连接对象时使用哪个文件描述符。因此,如果不传递
    parent\u连接
    ,您不知道要关闭哪个描述符,在许多应用程序中,哪个描述符可能不是问题。但是,例如,如果您有多个worker使用相同的连接(这需要锁定),那么如果worker中的描述符仍然打开,则在父级中调用close来通知它们停止将不起作用。