最近手頭有個需求是這樣的,定期檢查數據庫獲取失敗任務並且進行重啟。最早想到的是添加一個生產者&&消費者隊列,但是發現很多棘手的問題。
1.重啟任務是調用的一個shell腳本然后在腳本中又調用python程序,所以任務完成的狀態回傳略糾結。
2.重啟任務有多種重啟方式,要根據任務的不同FailStat來判斷重啟方式,這樣的話隊列中不僅要有任務名稱,還需要狀態碼
3.Python里的原生Queue不會進行去重,可能會導致隊列中對失敗任務無論重啟成功與否會進行多次重跑。
在StackOverflow上看了一些文章,都是推薦拓展Queue,看了看Queue.Queue的源代碼,發現果然很適合拓展:
# Override these methods to implement other queue organizations
# (e.g. stack or priority queue).
# These will only be called with appropriate locks held
# Initialize the queue representation
def _init(self, maxsize):
self.queue = deque()
def _qsize(self, len=len):
return len(self.queue)
# Put a new item in the queue
def _put(self, item):
self.queue.append(item)
# Get an item from the queue
def _get(self):
return self.queue.popleft()
So,自己通過字典來實現了一個類似鏈表的類,然后繼承Queue.Queue並重寫方法,實現了一個新的有序不重復隊列:
#!/usr/bin/env python
# Filename:ordered_map_queue.py
# -*- encoding:utf-8 -*-
import sys
import Queue
class Link():
''' No repeat link '''
def __init__(self):
self.map = {}
self.tail = "head"
self.map["head"] = {"stat":0, "next":"null"}
def __contains__(self,key):
return key in self.map
def __len__(self):
return len(self.map)-1
def isEmpty(self):
if self.getHead() == "null":
return True
else:
return False
def clearLink(self):
self.map.clear()
def getTail(self):
return self.tail
def getHead(self):
return self.map["head"]["next"]
def add(self, string):
# self.test_output("OrderedMapQueue")
args = string.split('\t')
item = args[0]
stat = args[1]
if item not in self.map:
self.map[item] = {"stat":stat, "next":"null"}
self.map[self.tail]["next"] = item
self.tail = item
def pop(self):
if not self.isEmpty():
head_task = self.map["head"]["next"]
rt_value = "%s\t%s" % (head_task, self.map[head_task]["stat"])
self.map["head"]["next"] = self.map[head_task]["next"]
del self.map[head_task]
if head_task == self.tail:
self.tail = "head"
return rt_value
return None
def test_output(self, name=""):
print >>sys.stderr, name
print >>sys.stderr, "-" * 10 + "TEST_OUTPUT" + "-" * 10
print >>sys.stderr, "Tail: %s\nHead: %s\nLength: %s" % (self.getTail(), self.getHead(), self.__len__())
head = "head"
while head != "null":
print >>sys.stderr, "%s\t%s\t%s" % (head, self.map[head]["stat"], self.map[head]["next"])
head = self.map[head]["next"]
print >>sys.stderr, "-" * 31
class OrderedMapQueue(Queue.Queue):
''' ordered-map queue '''
def _init(self, maxsize=0):
self.queue = Link()
def _put(self, item):
self.queue.add(item)
def _get(self):
return self.queue.pop()
def _qsize(self):
return self.queue.__len__()
if __name__ == "__main__":
#mylink = Link()
#mylink.add("task1","-1")
#mylink.add("task2","-2")
#mylink.add("task3","-1")
#mylink.test_output()
myqueue = OrderedMapQueue()
myqueue.put("task2\t-2")
myqueue.put("task3\t-1")
myqueue.put("task1\t-2")
myqueue.put("task3\t-1")
myqueue.put("task3\t-2")
myqueue.queue.test_output()
print myqueue.get()
myqueue.queue.test_output()
print myqueue.get()
myqueue.queue.test_output()
print myqueue.get()
myqueue.queue.test_output()
自己菜鳥一只,其中肯定有不少問題或者可改進的,希望大家能多多支出,我定會認真修改,多謝~
另外,推薦幾個拓展Queue的連接:
http://stackoverflow.com/questions/16506429/check-if-element-is-already-in-a-queue/16506527#16506527
http://stackoverflow.com/questions/8482619/proper-way-to-extend-python-queue
