把多进程分布到多台机器上
import random,time,queue
from multiprocessing.managers import BaseManager
#发送任务的队列
task_queue=queue.Queue()
#接受结果的队列
result_queue=queue.Queue()
#从BaseManager继承的QueueManager
class QueueManager(BaseManager):
pass
#把两个Queue都注册到网络上,callable参数关联了Queue对象
#callable ?????
if __name__=='__main__':
# QueueManager.register('get_task_queue',callable=lambda:task_queue)
# QueueManager.register('get_result_queue',callable=lambda:task_queue)
#不能用匿名函数,自己定义一下代替
#替代原来的匿名函数
def get_task_queue():
global task_queue
return task_queue
#替代原来的匿名函数
def get_result_queue():
global result_queue
return result_queue
#绑定端口5000,设置验证码‘abc’
#????
manager=QueueManager(address=('',5000),authkey=b'abc')
#启动Queue
manager.start()
#通过网络访问的Queue的对象
task=maneger.get_task_queue()
result=maneger.get_result_queue()
#放任务进去
for i in range(10):
n=random.randint(0,10000)
print('put task %d...' %n)
task.put(n)
#从result队列读取结果
print('try get result..')
for i in rang(10):
r=result.get(timeout=10)
print('result:%s' %r)
#关闭
manager.shutdown()
print('master exit')
总结如下:
- linux下创建进程使用fork(),windows平台下创建进程使用CreateProccess().
- fork()调用之后,没有写操作之前,与父进程共享一份内存,并没有真正拥有所谓多进程的”私有内存”. 而CreateProccess()每次执行之后,都确保子进程拥有新的内存空间.
- 这样设计的原因可以从linux和windows多进程的应用场景的差别来理解.fork诞生于无线程时代,因此fork()之后不exec的话,作用与多线程非常相似,可以理解为没有线程概念下的一种解决方案.而CreateProccess则更像创建兄弟进程, 创建的进程都保证独立存在.
- 这种差别直接体现在multiprocessing模块当中,在不同平台下使用不同的方法创建例子中的manager进程. 在windows下通过将父进程的环境进行序列化存储之后,再传入createProccess当中.
- 问题在于pickling序列化中对匿名函数的不支持,导致创建进程失败.
- 因此把匿名函数用函数替代即可解决.
改动点有两个:
取消匿名函数
加入if name == main 判断. 第二点是windows平台对于python多进程实现的要求.主要为了防止循环import
import time, sys, queue
from multiprocessing.managers import BaseManager
# 创建类似的QueueManager:
class QueueManager(BaseManager):
pass
# 由于这个QueueManager只从网络上获取Queue,所以注册时只提供名字:
QueueManager.register('get_task_queue')
QueueManager.register('get_result_queue')
# 连接到服务器,也就是运行task_master.py的机器:
server_addr = '127.0.0.1'
print('Connect to server %s...' % server_addr)
# 端口和验证码注意保持与task_master.py设置的完全一致:
m = QueueManager(address=(server_addr, 5000), authkey=b'abc')
# 从网络连接:
m.connect()
# 获取Queue的对象:
task = m.get_task_queue()
result = m.get_result_queue()
# 从task队列取任务,并把结果写入result队列:
for i in range(10):
try:
n = task.get(timeout=1)
print('run task %d * %d...' % (n, n))
r = '%d * %d = %d' % (n, n, n*n)
time.sleep(1)
result.put(r)
except Queue.Empty:
print('task queue is empty.')
# 处理结束:
print('worker exit.')
没有跑出来
学习
https://blog.csdn.net/Imagine_Dragon/article/details/77689194