self._semlock = _multiprocessing.SemLock._rebuild(*state) FileNotFoundError

在Mac中运行python多进程程序出现如下问题(multiprocessing):

...
self._semlock = _multiprocessing.SemLock._rebuild(*state)
FileNotFoundError: [Errno 2] No such file or directory
...
 self._semlock = _multiprocessing.SemLock._rebuild(*state)
FileNotFoundError: [Errno 2] No such file or directory

运行一下代码导致:

from multiprocessing import Process, Queue

def download_data(q):
    data = [1,2,3]
    for i in data:
        q.put(i)    # 数据入队列


def handle_data(q):
    while True:
        num = q.get()  # 出队列
        print(num)
        if q.empty():
            break

if __name__ == '__main__':
    q = Queue()
    p1 = Process(target=download_data, args=(q,))
    p2 = Process(target=handle_data, args=(q,))

    p1.start()
    p2.start()

错误原因:
Python创建的子线程执行的内容, 和启动该进程的方式有关. 而不同的操作系统,启动进程的方式不同, 大致分为以下3种:

  1. spawn: 使用此方式启动进程, 只会执行和target参数或者run()方法相关的代码. Windows平台只能使用此方法. 此方式启动进程的效率最低.
  2. fork: 使用此方式启动的进程, 基本等同于主进程(复刻主进程, 主进程拥有的资源, 子进程都有). 所以, 该方式创建的子进程会从创建位置起, 和主进程一样执行程序中的代码. 此启动方式适用于Unix和Linux.
  3. forserver: 使用此方式, 程序将会启动一个服务器进程. 即当程序每次请求启动新进程时, 父进程都会连接到该服务器进程, 请求有服务器进程来创建新进程. 通过这种方式启动的进程不需要从父进程继承资源. 此方式使用与Unix,

**这里Mac电脑默认启动进程的方式是fork, 而Python默认的方式是spawn, 所有需要将python启动进程的方式做修改: **
这里提供两种方式:

  1. 添加 set_start_method(‘fork’)
  2. 使用 get_context() 来获取上下文对象。上下文对象与多处理模块具有相同的API,并允许在同一程序中使用多个启动方法. ctx = get_context(‘fork’) ; ctx.Process…
  3. 使用multiprocess.Queue()和multiprocess.Process()替换multiprocessing的.(这里略)

解决1: set_start_method(‘fork’)

from multiprocessing import Process, Queue, set_start_method

def download_data(q):
    data = [1,2,3]
    for i in data:
        q.put(i)    # 数据入队列


def handle_data(q):
    while True:
        num = q.get()  # 出队列
        print(num)
        if q.empty():
            break

if __name__ == '__main__':
    set_start_method('fork')
    q = Queue()
    p1 = Process(target=download_data, args=(q,))
    p2 = Process(target=handle_data, args=(q,))

    p1.start()
    p2.start()

解决2: 使用get_context(‘fork’)

from multiprocessing import Process, Queue, set_start_method, get_context

def download_data(q):
    data = [1,2,3]
    for i in data:
        q.put(i)    # 数据入队列


def handle_data(q):
    while True:
        num = q.get()  # 出队列
        print(num)
        if q.empty():
            break

if __name__ == '__main__':
    # set_start_method('fork')
    q = Queue()
    ctx = get_context('fork')
    p1 = ctx.Process(target=download_data, args=(q,))
    p2 = ctx.Process(target=handle_data, args=(q,))

    p1.start()
    p2.start()

问题解决了…


版权声明:本文为weixin_45592364原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。