分布式进程
Python的multiprocessing模块不但支持多进程,其中的managers子模块还支持吧多进程分布到多台机器上。
Demo
只能在unix(类unix)环境运行,windows会报错
具体解释
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431929340191970154d52b9d484b88a7b343708fcc60000#0
运行示例
服务端
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 分布进程-服务端
import random, time, queue
from multiprocessing.managers import BaseManager
# 发送任务的队列
task_queue = queue.Queue()
# 接收任务的队列
result_queue = queue.Queue()
# 从 BaseManager继承的 QueueManager
class QueueManager(BaseManager):
pass
def get_task_queue():
global task_queue
return task_queue
# 把两个Queue都注册到网络上,callable参数关联了 Queue 对象
QueueManager.register("get_task_queue", callable = get_task_queue)
QueueManager.register("get_result_queue", callable = lambda:result_queue)
# 绑定端口5000,设置验证码为"abc"
manager = QueueManager(address=("", 5000), authkey=b"abc")
# 启动 Queue
manager.start()
# 获取通过网络访问的 Queue 对象
task = manager.get_task_queue()
result = manager.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 range(10):
r = result.get(timeout = 10)
print("结果 %s" % r)
# 关闭
manager.shutdown()
print("manage exit")
客户端
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 分布进程-客户端
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("连接服务器 %s" % server_addr)
# 端口和验证码注意和服务器一致
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" %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")
Window无法正常执行,例如
D:\PythonProject>Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\ProgramData\Anaconda3\lib\multiprocessing\spawn.py", line 99, in spawn_main
new_handle = reduction.steal_handle(parent_pid, pipe_handle)
File "C:\ProgramData\Anaconda3\lib\multiprocessing\reduction.py", line 82, in steal_handle
_winapi.PROCESS_DUP_HANDLE, False, source_pid)
OSError: [WinError 87] 参数错误。
python task_worker.py
连接服务器 127.0.0.1
Traceback (most recent call last):
File "task_worker.py", line 23, in <module>
m.connect()
File "C:\ProgramData\Anaconda3\lib\multiprocessing\managers.py", line 489, in connect
conn = Client(self._address, authkey=self._authkey)
File "C:\ProgramData\Anaconda3\lib\multiprocessing\connection.py", line 487, in Client
c = SocketClient(address)
File "C:\ProgramData\Anaconda3\lib\multiprocessing\connection.py", line 614, in SocketClient
s.connect(address)
ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。
这个简单的Master/Worker模型有什么用?其实这就是一个简单但真正的分布式计算,把代码稍加改造,启动多个worker,就可以把任务分布到几台甚至几十台机器上,比如把计算n*n的代码换成发送邮件,就实现了邮件队列的异步发送。
看来这个demo暂时无法看效果了,可惜