Python中的使用标准queue模块就可以建立多进程使用的队列,但是使用redisredis-queue(rq)模块使这一操作更加简单。

Part 1.

比如首先我们使用队列来简单的储存数据:我们选用redis list类型,其他类型的数据操作可以参考这个文章

redis_queue.py文件中:

import redis

class RedisQueue(object):
def __init__(self, name, namespace='queue', **redis_kwargs):
# redis的默认参数为:host='localhost', port=6379, db=0, 其中db为定义redis database的数量
self.__db= redis.Redis(**redis_kwargs)
self.key = '%s:%s' %(namespace, name) def qsize(self):
return self.__db.llen(self.key) # 返回队列里面list内元素的数量 def put(self, item):
self.__db.rpush(self.key, item) # 添加新元素到队列最右方 def get_wait(self, timeout=None):
# 返回队列第一个元素,如果为空则等待至有元素被加入队列(超时时间阈值为timeout,如果为None则一直等待)
item = self.__db.blpop(self.key, timeout=timeout)
# if item:
# item = item[1] # 返回值为一个tuple
return item def get_nowait(self):
# 直接返回队列第一个元素,如果队列为空返回的是None
item = self.__db.lpop(self.key)
return item

input.py文件中:

from redis_queue import RedisQueue
import time q = RedisQueue('rq') # 新建队列名为rq
for i in range(5):
q.put(i)
print "input.py: data {} enqueue {}".format(i, time.strftime("%c"))
time.sleep(1)

output.py文件中:

from redis_queue import RedisQueue
import time q = RedisQueue('rq')
while 1:
result = q.get_nowait()
if not result:
break
print "output.py: data {} out of queue {}".format(result, time.strftime("%c"))
time.sleep(2)

test_run.sh文件中:

python input.py &
python output.py &

在terminal中运行test.sh的结果如下:

input.py: data 0 enqueue Fri Nov 10 10:51:37 2017
output.py: data 0 out of queue Fri Nov 10 10:51:37 2017
input.py: data 1 enqueue Fri Nov 10 10:51:38 2017
output.py: data 1 out of queue Fri Nov 10 10:51:38 2017
input.py: data 2 enqueue Fri Nov 10 10:51:39 2017
output.py: data 2 out of queue Fri Nov 10 10:51:39 2017
input.py: data 3 enqueue Fri Nov 10 10:51:40 2017
output.py: data ('queue:rq', '3') out of queue Fri Nov 10 10:51:40 2017
input.py: data 4 enqueue Fri Nov 10 10:51:41 2017
output.py: data ('queue:rq', '4') out of queue 1510282301.69

其中lpop返回的是一个队列名+元素值的tuple,并且返回的数值默认为string

Part 2.

队列里面可以添加任意object,因此可以添加函数到多个队列来实现多线程并发的效果。

首先,建立一个rq work进程(写在worker.py脚本中)来监听队列

import redis
from rq import Worker, Queue, Connection listen = ['default']
redis_url = "redis://localhost:6379" # redis server 默认地址
conn = redis.from_url(redis_url) def square_function(x):
return x*x if __name__ == '__main__':
with Connection(conn): # 建立与redis server的连接
worker = Worker(list(map(Queue, listen))) # 建立worker监听给定的队列
worker.work()

然后python worker.py启动redis server

test.py文件中:

from rq import Queue
from rq.job import Job
from worker import square_function, conn
import time q = Queue(connection=conn) job = q.enqueue_call(square_function, args=(5, ), result_ttl=5000) # 保存结果5000s
job_id = job.get_id()
print job_id result1 = Job.fetch(job_id, connection=conn)
print result1.is_finished time.sleep(1) # 等待队列里任务完成 result2 = Job.fetch(job_id, connection=conn)
print result2.return_value

上面文件的输出结果为:

98dc6f58-9333-48f7-88c1-c4de1cc9e5cf  # job id
False # 任务尚未完成
25 # 任务完成,输出结果

: 调用的square_function不允许和任务发起在同一个脚本,否则会报错ValueError: Functions from the __main__ module cannot be processed by workers

当与flask一起使用时:

app.py文件中:

from rq import Queue
from rq.job import Job
from worker import conn, square_function from flask import Flask, request app = Flask(__name__) q = Queue(connection=conn) # 建立与Redis server的连接并初始化一个队列 @app.route("/", methods=['POST'])
def index():
x = request.get_data() # string 类型
job = q.enqueue_call(square_function, args=(int(x), ), result_ttl=5000) # 最后的参数为RQ保留结果的时间
return job.get_id() # 返回job的id @app.route('/result/<job_key>', methods=['GET'])
def get_results(job_key):
job = Job.fetch(job_key, connection=conn) # 获取根据job_id获取任务的返回值
if job.is_finished: # 检验是否完成
return str(job.result), 200
else:
return "Wait!", 202 if __name__ == "__main__":
app.run('0.0.0.0', port=5000)

python app.py启动flask服务

test.py文件:

import requests
import time post_url = "http://localhost:5000"
post_result = requests.post(post_url, data={'x': 2})
job_id = post_result.content
print job_id time.sleep(1) get_url = "http://localhost:5000/result/{}".format(job_id)
get_result = requests.get(get_url)
print get_result.content

获得的结果如下:

067306e9-f13b-4b6a-93dc-2f5b457a78b7  # job id
4 # job返回值

参考:

  1. https://realpython.com/blog/python/flask-by-example-implementing-a-redis-task-queue/
  2. http://peter-hoffmann.com/2012/python-simple-queue-redis-queue.html
  3. http://python-rq.org/docs/
  4. https://www.cnblogs.com/melonjiang/p/5342505.html
  5. http://xiaorui.cc/2015/11/11/解决python-rq获取返回结果和异常的问题/

python中利用redis构建任务队列(queue)的更多相关文章

  1. python中利用队列asyncio.Queue进行通讯详解

    python中利用队列asyncio.Queue进行通讯详解 本文主要给大家介绍了关于python用队列asyncio.Queue通讯的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细 ...

  2. Python中利用函数装饰器实现备忘功能

    Python中利用函数装饰器实现备忘功能 这篇文章主要介绍了Python中利用函数装饰器实现备忘功能,同时还降到了利用装饰器来检查函数的递归.确保参数传递的正确,需要的朋友可以参考下   " ...

  3. python中利用matplotlib绘图可视化知识归纳

    python中利用matplotlib绘图可视化知识归纳: (1)matplotlib图标正常显示中文 import matplotlib.pyplot as plt plt.rcParams['fo ...

  4. redis的安装使用以及在python中操作redis

    一.Redis介绍: Redis可以看作是一个key-value的存储系统,它为我们提供了丰富的数据结构,包括lists,sets,ordered sets和hashes.还包括了对这些数据结构的丰富 ...

  5. Python中的 redis keyspace 通知

    介绍 Redis是内存中的数据结构存储,用于缓存.高速数据摄取.处理消息队列.分布式锁定等等. 与其他内存存储相比,使用Redis的优势在于它提供了持久性和数据结构,比如列表.集合.排序集合和散列. ...

  6. python中的Redis键空间通知(过期回调)

    介绍 Redis是一个内存数据结构存储库,用于缓存,高速数据摄取,处理消息队列,分布式锁定等等. 使用Redis优于其他内存存储的优点是Redis提供持久性和数据结构,如列表,集合,有序集和散列. 在 ...

  7. Python中利用原始套接字进行网络编程的示例

    Python中利用原始套接字进行网络编程的示例 在实验中需要自己构造单独的HTTP数据报文,而使用SOCK_STREAM进行发送数据包,需要进行完整的TCP交互. 因此想使用原始套接字进行编程,直接构 ...

  8. (数据科学学习手札145)在Python中利用yarl轻松操作url

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,在诸如网络爬虫.web应用开发 ...

  9. Python中利用LSTM模型进行时间序列预测分析

    时间序列模型 时间序列预测分析就是利用过去一段时间内某事件时间的特征来预测未来一段时间内该事件的特征.这是一类相对比较复杂的预测建模问题,和回归分析模型的预测不同,时间序列模型是依赖于事件发生的先后顺 ...

随机推荐

  1. JavaScript_作用域(2017-03-16)

    这里写的还不够清楚. 建议去看:王福朋 的博客的加深理解. 深入理解javascript原型和闭包(8)——简述[执行上下文]上 深入理解javascript原型和闭包(9)——简述[执行上下文]下 ...

  2. PS文字生成头像

    链接: 教你用PS把文字拼成肖像.... 28个文字组成的肖像画欣赏

  3. innodb文件

    参数文件 日志文件 socket文件 pid文件 mysql表结构文件 存储引擎文件 1. 错误日志 启用错误日志方法 /etc/init.d/mysql启动文件中 /usr/bin/mysqld_s ...

  4. 写一个针对IQueryable<T>的扩展方法支持动态排序

    所谓的动态排序是指支持任意字段.任意升序降序的排序.我们希望在客户端按如下格式写: localhost:8000/api/items?sort=titlelocalhost:8000/api/item ...

  5. qt不能调试

    在F5执行qt的调试时,提示:unknown debugger type "No engine" 需要下载debug调试工具,win7的下载位于:https://www.micro ...

  6. 实录分享 | 计算未来轻沙龙:揭秘AutoML技术(视频 + PPT)

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/c9Yv2cf9I06K2A9E/article/details/83542784 10 月 27 日 ...

  7. WPF背景图

    方法一:xaml中:<控件>  <控件.Background><ImageBrush ImageSource="/程序集;component/images/xx ...

  8. Android官方开发文档Training系列课程中文版:性能优化建议

    原文地址:http://android.xsoftlab.net/training/articles/perf-tips.html 本篇文章主要介绍那些能够提升总体性能的微小优化点.它与那些能突然改观 ...

  9. scala sortBy and sortWith

    sortBy: sortBy[B](f: (A) ⇒ B)(implicit ord: math.Ordering[B]): List[A] 按照应用函数f之后产生的元素进行排序 sorted: so ...

  10. Uber使用Swift重写APP的踩坑经历及解决方案(转载)

    本文出自Uber移动架构和框架组负责人托马斯·阿特曼于2016年在湾区Swift峰会上的演讲,分享了使用Swfit重写Uber的好与坏.以下为译文: 我是托马斯·阿特曼,目前是Uber移动架构和框架组 ...