您好,登錄后才能下訂單哦!
直奔主題,在用多線程寫一個爬蟲項目時,很自然的想到用“生產者-消費者”模式,但是又想實現一個額外的需求,即如果爬蟲爬到了隊列中已存在的url,則不進行入隊操作。想實現這個,大概面臨兩個問題:
Queue
對象不支持in
操作Queue
對象外部通過if item in q
這種形式也行不通,因為該過程無鎖,多線程情況下就無法保證查詢結果的準確性進而觀察了一下queue模塊的源代碼,因為Queue類是基于deque類實現的,那么就好辦了:對put
方法稍加改造,增加一個unique
參數,依據此參數是否為True,在底層的deque中判斷要加入的元素的存在性,以此可實現類似set的特性。
put方法源代碼:
def put(self, item, block=True, timeout=None):
with self.not_full:
if self.maxsize > 0:
if not block:
if self._qsize() >= self.maxsize:
raise Full
elif timeout is None:
while self._qsize() >= self.maxsize:
self.not_full.wait()
elif timeout < 0:
raise ValueError("'timeout' must be a non-negative number")
else:
endtime = time() + timeout
while self._qsize() >= self.maxsize:
remaining = endtime - time()
if remaining <= 0.0:
raise Full
self.not_full.wait(remaining)
self._put(item)
self.unfinished_tasks += 1
self.not_empty.notify()
修改后的put方法
def put(self, item, block=True, timeout=None, unique=False):
"""增加了unique參數"""
with self.not_full:
#----- 以下三行為新增代碼 -----#
if unique:
if item in self.queue:
return
#----- 新增代碼結束 -----#
if self.maxsize > 0:
if not block:
if self._qsize() >= self.maxsize:
raise Full
elif timeout is None:
while self._qsize() >= self.maxsize:
self.not_full.wait()
elif timeout < 0:
raise ValueError("'timeout' must be a non-negative number")
else:
endtime = time() + timeout
while self._qsize() >= self.maxsize:
remaining = endtime - time()
if remaining <= 0.0:
raise Full
self.not_full.wait(remaining)
self._put(item)
self.unfinished_tasks += 1
self.not_empty.notify()
當然也可以仿照put_nowait
方法增加一個快捷方法put_unique
,如下
def put_unique(self, item, block=True, timeout=None):
return self.put(item, block, timeout, unique=True)
Have fun!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。