创建服务进程
1.建立队列Queue,用来进行进程间通信
2.把第一步建立的队列在网络上注册,暴露给其他进程(主机),注册后获得网络队列,相当于本地队列的映像
3.建立一个对象(Queuemanager(BaseManager))实例manager,绑定端口和验证口令
4.启动第三步中建立的实例,即启动管理manager, 监管信息通道
5. 通过管理实例的方法获得通过网络访问的Queue 对象,即再把网络队列实体化成可以使用的本地队列
6.创建任务到“本地”队列中,自动上传任务到网络队列中,分配给任务进程进行处理
代码如下taskManager_win.py:
import random, time
from multiprocessing import Queue
from multiprocessing.managers import BaseManager
from multiprocessing import freeze_support
# 任务个数
task_number = 10
# 第一步: 建立task_queue和result_queue, 用来存放任务和结果
task_queue = Queue()
result_queue = Queue()
def get_task():
return task_queue
def get_result():
return result_queue
# 创建QueueManager
class Queuemanager(BaseManager):
pass
def win_run():
# Windows下绑定调用接口不能使用lambda, 所以只能先定义函数再绑定
# 第二步: 把创建的两个队列注册在网络上,利用register方法,callable参数关联了Queue对象,并将Queue对象在网络上暴露
Queuemanager.register('get_task_queue', callable=get_task)
Queuemanager.register('get_result_queue', callable=get_result)
# 第三步:绑定端口8001,设置验证口令'chongyun',这相当于对象的初始化,windows下需要填写IP地址,Linux下不填默认为本地
manager = Queuemanager(address=('127.0.0.1', 8001), authkey='chongyun'.encode('utf-8'))
# 第四步,启动管理,监听信息通道
manager.start()
try:
# 第五步:通过管理实例的方法获得通过网络访问的Queue对象
task = manager.get_task_queue()
result = manager.get_result_queue()
# 第六步:添加任务
for url in ["ImageUrl_"+str(i) for i in range(10)]:
print('put task %s ...' % url)
task.put(url)
# 获取返回结果
print('try get result...')
for i in range(10):
print('result is %s' % result.get(timeout=10))
except Exception as e:
print(e)
finally:
# 关闭管理
manager.shutdown()
if __name__ == '__main__':
# Windows 下多进程可能会有问题,添加这句可以缓解
freeze_support()
win_run()
创建任务进程:
1.使用 QueueManager 注册用于获取Queue的方法名称,任务进程只能通过名称来在网络上获取Queue
2.连接服务器, 端口和验证口令注意保持与服务进程中完全一致
3.从网络上获取Queue,进行本地化
4.从task队列获取任务,并把结果写入result队列
代码如下taskWorker.py:
import time
from multiprocessing.managers import BaseManager
# 创建类似的QueueManager:
class QueueManager(BaseManager):
pass
# 第一步:使用QueueManager注册用于获取Queue的方法名称
QueueManager.register('get_task_queue')
QueueManager.register('get_result_queue')
print('worker exit.')
先运行taskManager_win.py,运行结果:
put task ImageUrl_0 ...
put task ImageUrl_1 ...
put task ImageUrl_2 ...
put task ImageUrl_3 ...
put task ImageUrl_4 ...
put task ImageUrl_5 ...
put task ImageUrl_6 ...
put task ImageUrl_7 ...
put task ImageUrl_8 ...
put task ImageUrl_9 ...
try get result...
再运行taskWorker.py,显示运行结果:
Connect to server 127.0.0.1....
run task download ImageUrl_0...
run task download ImageUrl_1...
run task download ImageUrl_2...
run task download ImageUrl_3...
run task download ImageUrl_4...
run task download ImageUrl_5...
run task download ImageUrl_6...
run task download ImageUrl_7...
run task download ImageUrl_8...
run task download ImageUrl_9...
worker exit.
同时taskManager_win.py运行结果继续显示
try get result...
result is ImageUrl_0 ---> sucess
result is ImageUrl_1 ---> sucess
result is ImageUrl_2 ---> sucess
result is ImageUrl_3 ---> sucess
result is ImageUrl_4 ---> sucess
result is ImageUrl_5 ---> sucess
result is ImageUrl_6 ---> sucess
result is ImageUrl_7 ---> sucess
result is ImageUrl_8 ---> sucess
result is ImageUrl_9 ---> sucess
Process finished with exit code 0
其中需要注意的事项有:
1. 如果Queue导入 为from queue import Queue
则可能报错 python TypeError: can't pickle _thread.RLock objects
解决方法:这是因为queue.Queue()是线程的原因,需要把import queue改成from multiprocessing import Queue,然后用Queue()换掉queue.Queue()
2. TypeError: string argument without an encoding
解决方法: 在字符串后加上.encode('utf-8')
3. TypeError: 'Queue' object is not callable
解决方法:检查"callable="后的函数名是否错误,以及函数调用是否多加了().