python分布式进程(windows下)
分布式进程:
在Thread和Process中,应当优选Process,因为Process更稳定,而且,Process可以分布到多台机器上,而Thread最多只能分布到同一台机器的多个CPU上。
Python的multiprocessing模块不但支持多进程,其中managers子模块还支持把多进程分布到多台机器上。一个服务进程可以作为调度者,将任务分布到其他多个进程中,依靠网络通信。由于managers模块封装很好,不必了解网络通信的细节,就可以很容易地编写分布式多进程程序。
举个例子:如果我们已经有一个通过Queue通信的多进程程序在同一台机器上运行,现在,由于处理任务的进程任务繁重,希望把发送任务的进程和处理任务的进程分布到两台机器上。怎么用分布式进程实现?
原有的Queue可以继续使用,但是,通过managers模块把Queue通过网络暴露出去,就可以让其他机器的进程访问Queue了。
我们先看服务进程,服务进程负责启动Queue,把Queue注册到网络上,然后往Queue里面写入任务:
下面的代码是在windows下运行的,所以出现了各种问题:
# 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# 把两个Queue都注册到网络上, callable参数关联了Queue对象:
QueueManager.register('get_task_queue', callable=lambda: 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 results...')
for i in range(10):r = result.get(timeout=10)print('Result: %s' % r)
# 关闭:
manager.shutdown()
print('master exit.')
在windows命令行终端的运行结果:
由错误信息改代码:
# coding=utf-8import random,time, Queue
from multiprocessing.managers import BaseManager
from multiprocessing import freeze_supporttask_queue = Queue.Queue() # 发送任务的队列:
result_queue = Queue.Queue() # 接收结果的队列:
class QueueManager(BaseManager): # 从BaseManager继承的QueueManager:pass
# windows下运行
def return_task_queue():global task_queuereturn task_queue # 返回发送任务队列
def return_result_queue ():global result_queuereturn result_queue # 返回接收结果队列def test():# 把两个Queue都注册到网络上, callable参数关联了Queue对象,它们用来进行进程间通信,交换对象#QueueManager.register('get_task_queue', callable=lambda: task_queue)#QueueManager.register('get_result_queue', callable=lambda: result_queue)QueueManager.register('get_task_queue', callable=return_task_queue) QueueManager.register('get_result_queue', callable=return_result_queue)# 绑定端口5000, 设置验证码'abc':#manager = QueueManager(address=('', 5000), authkey=b'abc')# windows需要写ip地址manager = QueueManager(address=('127.0.0.1', 5000), authkey=b'abc')manager.start() # 启动Queue: # 获得通过网络访问的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 results...') for i in range(10):# 这里加了异常捕获try:r = result.get(timeout=5)print('Result: %s' % r)except Queue.Empty:print('result queue is empty.')# 关闭: manager.shutdown() print('master exit.')
if __name__=='__main__':freeze_support()print('start!')test()
运行结果:
对比上段代码改变的地方有:
# 把两个Queue都注册到网络上, callable参数关联了Queue对象
QueueManager.register('get_task_queue',callable=return_task_queue)
QueueManager.register('get_result_queue',callable=return_result_queue)
其中task_queue和result_queue是两个队列,分别存放任务和结果。它们用来进行进程间通信,交换对象。
官网上有如下例子。
# coding=utf-8
from multiprocessing import Process, Queue
def f(queue):queue.put([42, None, 'hello'])if __name__ == '__main__': q = Queue() # 创建队列qp = Process(target=f, args=(q,)) # 创建一个进程p.start()print(q.get()) # 打印列表[42, None, 'hello']p.join()
其中列表[42, None, ‘hello’]从新建p进程传到了主进程中。
因为是分布式的环境,放入queue中的数据需要等待Workers机器运算处理后再进行读取,这样就需要对queue用QueueManager进行封装放到网络中。这是通过下面这句
QueueManager.register('get_task_queue',callable=return_task_queue)
实现的,我们给return_task_queue的网络调用接口取了一个名get_task_queue,而return_result_queue的名字是get_result_queue,方便区分对哪个queue进行操作。
task.put(n)即是对task_queue进行写入数据,相当于分配任务。而result.get()即是等待workers处理后返回的结果
# windows需要写ip地址manager = QueueManager(address=('127.0.0.1', 5000), authkey=b'abc')
这点不同于linux操作系统,必须写ip地址
if __name__=='__main__':freeze_support()print('start!')test()
windows必须有 if name==’main‘: 这点从报错的信息可以看出
中间加入了捕获异常,使代码运行完整,运行结果更容易看懂,在运行的时候最好用cmd终端。
下面是Worker的代码:
# 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('Connect to server %s...' % server_addr)
# 端口和验证码注意保持与task_master.py设置的完全一致:
m = QueueManager(address=(server_addr, 5000), authkey=b'abc')
# 从网络连接:
try:m.connect()
except:print('请先启动task_master.py!')#sys.exit("sorry, goodbye!");
# 获取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.')
这个简单的Master/Worker模型有什么用?其实这就是一个简单但真正的分布式计算,把代码稍加改造,启动多个worker,就可以把任务分布到几台甚至几十台机器上,比如把计算n*n的代码换成发送邮件,就实现了邮件队列的异步发送。
Queue对象存储在哪?注意到task_worker.py中根本没有创建Queue的代码,所以,Queue对象存储在task_master.py进程中:
task_worker这里的QueueManager注册的名字必须和task_manager中的一样。对比上面的例子,可以看出Queue对象从另一个进程通过网络传递了过来。只不过这里的传递和网络通信由QueueManager完成。
运行结果:
运行task_master.py
运行task_worker.py
此运行是在同一台电脑上
参考:
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431929340191970154d52b9d484b88a7b343708fcc60000
python分布式进程(windows下)相关推荐
- 使用Python批量删除windows下特定目录的N天前的旧文件实战:Windows下批量删除旧文件、清除缓存文件、解救C盘、拒绝C盘爆炸
使用Python批量删除windows下特定目录的N天前的旧文件实战:Windows下批量删除旧文件.清除缓存文件.解救C盘.拒绝C盘爆炸 目录
- python定时开关机的代码_用python写一个windows下的定时关机脚本(推荐)
由于本人经常使用笔记本共享WiFi,但是又不想笔记本开机一夜(为了低碳环保嘛 ~_~!),所以每次都要用使用DOS命令关机,感觉好麻烦.正好最近在学习Python,于是决定用python写一个定时关机 ...
- Python(pycharm)在windows下路径 ( ' / ' 与' \ ' )的问题
1.0 首先了解Python中与pycharm,windows交互的模块(这二个模块可以避免出现路径错误的问题) sys模块 (侧重Python与pycharm交互) 提供的与路径相关的方法有: __ ...
- 用python写一个windows下的定时关机脚本
由于本人经常使用笔记本共享WiFi,但是又不想笔记本开机一夜(为了低碳环保嘛 ~_~!),所以每次都要用使用DOS命令关机,感觉好麻烦.正好最近在学习python,于是决定用python写一个定时关机 ...
- python笔记:Windows下的 python-ldap 安装
Windows下的 python-ldap 安装 https://www.lfd.uci.edu/~gohlke/pythonlibs/#python-ldap 下载: python_ldap-3.3 ...
- python 学习之Windows 下的编码处理!
问题1: 1 Non-ASCII character '\xe9' in file 问题原因:程序编码上出现问题 解决方法:在程序头部加上代码 #-*- coding: UTF-8 -*- 设置代码编 ...
- [Python爬虫] 在Windows下安装PIP+Phantomjs+Selenium
最近准备深入学习Python相关的爬虫知识了,如果说在使用Python爬取相对正规的网页使用"urllib2 + BeautifulSoup + 正则表达式"就能搞定的话:那么动态 ...
- [Python爬虫] 在Windows下安装PhantomJS和CasperJS及入门介绍(上)
最近在使用Python爬取网页内容时,总是遇到JS临时加载.动态获取网页信息的困难.例如爬取CSDN下载资源评论.搜狐图片中的"原图"等,此时尝试学习Phantomjs和Caspe ...
- python进阶(四) windows下虚拟环境使用
虚拟环境作用: 1. 通常开发一个项目,会安装很多的第三方包,这时第三方包我们是安装在本机环境的.那么如果项目进行部署或移植的时候是不是要重新安装这些包???? 2.开发环境,同时在做两相项目,同时要 ...
最新文章
- ATAC-seq学习记录
- 一个视觉交互设计失败的案例
- httpclient 调取接口_HttpClient调用接口发送文件
- 记一次iis+aspx环境下利用http参数污染绕过waf
- java-ee-api_刷新器-Java EE 7概览
- Java中连接字符串的最佳方法
- 抱歉咯!今天偷个懒!!
- [复变函数]第17堂课 5 解析函数的 Laurent 展式与孤立奇点 5. 1 解析函数的 Laurent 展式...
- linux的文本,Linux文本处理
- 揭秘 DockerCon 重量级演讲嘉宾(四)
- (转)修改的T4代码生成器(续)
- PHP异步调用实现方式
- OpenCL简单入门
- CentOS7.2安装linux版QQ
- matlab磁盘内存,Matlab内存不足问题的解决【转】
- 再见beycond comapre,适合程序员使用的免费文件对比工具——CCompare1.14
- matlab gui中断程序,MATLAB GUI的中斷程序
- 日本人布置工作至少说5遍
- namecheap,namesilo域名注册优势,国外域名注册,2018 namesilo注册优惠码
- 3dsMax撤销不管用,3dsMax转成多边形之后无法撤回操作,3dsmax的操作步骤一直为空
热门文章
- OpenCV使用dnn从图像中解析人体部位的实例(附完整代码)
- OpenGL 四边形渲染的实例
- 浅谈C++函数的参数
- excel 平滑滚动_Excel怎么学 | 图表实战,销售数据的不同表达方式
- listener.ora--sqlnet.ora--tnsnames.ora的关系以及手工配置举例(转载:http://blog.chinaunix.net/uid-83572-id-5510.ht)
- 8.非关系型数据库(Nosql)之mongodb的应用场景(关系型数据库 和 Mongodb进行CRUD时数据用时的比较)
- tp5模板 使用php代码,thinkPHP的Html模板标签使用方法
- [C/C++] C++声明和定义的区别
- vs2010 出错:error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
- 谈VHDL/Verilog的可综合性以及对初学者的一些建议