在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种:
- spawn: 使用此方式启动进程, 只会执行和target参数或者run()方法相关的代码. Windows平台只能使用此方法. 此方式启动进程的效率最低.
- fork: 使用此方式启动的进程, 基本等同于主进程(复刻主进程, 主进程拥有的资源, 子进程都有). 所以, 该方式创建的子进程会从创建位置起, 和主进程一样执行程序中的代码. 此启动方式适用于Unix和Linux.
- forserver: 使用此方式, 程序将会启动一个服务器进程. 即当程序每次请求启动新进程时, 父进程都会连接到该服务器进程, 请求有服务器进程来创建新进程. 通过这种方式启动的进程不需要从父进程继承资源. 此方式使用与Unix,
**这里Mac电脑默认启动进程的方式是fork, 而Python默认的方式是spawn, 所有需要将python启动进程的方式做修改: **
这里提供两种方式:
- 添加 set_start_method(‘fork’)
- 使用 get_context() 来获取上下文对象。上下文对象与多处理模块具有相同的API,并允许在同一程序中使用多个启动方法. ctx = get_context(‘fork’) ; ctx.Process…
- 使用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()
问题解决了…