python 中的queue, deque

python3 deque(雙向隊列)html

建立雙向隊列python

import collections
d = collections.deque()

append(往右邊添加一個元素)linux

複製代碼
import collections
d = collections.deque()
d.append(1)
d.append(2)
print(d)

#輸出:deque([1, 2])
複製代碼

appendleft(往左邊添加一個元素)shell

複製代碼
import collections
d = collections.deque()
d.append(1)
d.appendleft(2)
print(d)

#輸出:deque([2, 1])
複製代碼

clear(清空隊列)數據結構

複製代碼
import collections
d = collections.deque()
d.append(1)
d.clear()
print(d)

#輸出:deque([])
複製代碼

copy(淺拷貝)app

複製代碼
import collections
d = collections.deque()
d.append(1)
new_d = d.copy()
print(new_d)

#輸出:deque([1])
複製代碼

count(返回指定元素的出現次數)post

複製代碼
import collections
d = collections.deque()
d.append(1)
d.append(1)
print(d.count(1))

#輸出:2
複製代碼

extend(從隊列右邊擴展一個列表的元素)this

複製代碼
import collections
d = collections.deque()
d.append(1)
d.extend([3,4,5])
print(d)

#輸出:deque([1, 3, 4, 5])
複製代碼

extendleft(從隊列左邊擴展一個列表的元素)url

複製代碼
import collections
d = collections.deque()
d.append(1)
d.extendleft([3,4,5])
print(d)
#
# #輸出:deque([5, 4, 3, 1])
複製代碼

index(查找某個元素的索引位置)spa

複製代碼
import collections
d = collections.deque()
d.extend(['a','b','c','d','e'])
print(d)
print(d.index('e'))
print(d.index('c',0,3))  #指定查找區間

#輸出:deque(['a', 'b', 'c', 'd', 'e'])
#     4
#     2
複製代碼

insert(在指定位置插入元素)

複製代碼
import collections
d = collections.deque()
d.extend(['a','b','c','d','e'])
d.insert(2,'z')
print(d)

#輸出:deque(['a', 'b', 'z', 'c', 'd', 'e'])
複製代碼

pop(獲取最右邊一個元素,並在隊列中刪除)

複製代碼
import collections
d = collections.deque()
d.extend(['a','b','c','d','e'])
x = d.pop()
print(x,d)

#輸出:e deque(['a', 'b', 'c', 'd'])
複製代碼

popleft(獲取最左邊一個元素,並在隊列中刪除)

複製代碼
import collections
d = collections.deque()
d.extend(['a','b','c','d','e'])
x = d.popleft()
print(x,d)

#輸出:a deque(['b', 'c', 'd', 'e'])
複製代碼

remove(刪除指定元素)

複製代碼
import collections
d = collections.deque()
d.extend(['a','b','c','d','e'])
d.remove('c')
print(d)

#輸出:deque(['a', 'b', 'd', 'e'])
複製代碼

reverse(隊列反轉)

複製代碼
import collections
d = collections.deque()
d.extend(['a','b','c','d','e'])
d.reverse()
print(d)

#輸出:deque(['e', 'd', 'c', 'b', 'a'])
複製代碼

rotate(把右邊元素放到左邊)

複製代碼
import collections
d = collections.deque()
d.extend(['a','b','c','d','e'])
d.rotate(2)   #指定次數,默認1次
print(d)

#輸出:deque(['d', 'e', 'a', 'b', 'c'])
複製代碼

 

queue模塊介紹

模塊實現了3種類型的隊列,區別在於隊列中條目檢索的順序不一樣。在FIFO隊列中,按照先進先出的順序檢索條目。在LIFO隊列中,最後添加的條目最早檢索到(操做相似一個棧)。在優先級隊列中,條目被保存爲有序的(使用heapq模塊)而且最小值的條目被最早檢索。

queue模塊定義了下面的類和異常:

class queue.Queue(maxsize=0)

FIFO隊列的構造器。maxsize爲一個整數,表示隊列的最大條目數。一旦隊列滿,插入將被阻塞直到隊列中存在空閒空間。若是maxsize小於等於0,隊列大小爲無限。maxsize默認爲0
複製代碼
import queue
import time

q = queue.Queue()

#FIFO隊列先進先出
q.put(2)
q.put(1)
q.put(3)

while not q.empty():
    next_item = q.get()
    print(next_item)
    time.sleep(1)

執行結果:
2
1
3
複製代碼

class queue.LifoQueue(maxsize=0)

LIFO隊列的構造器。maxsize是一個整數,表示隊列的最大條目數。一旦隊列滿,插入將被阻塞直到隊列中存在空閒空間。若是maxsize小於等於0,隊列大小爲無限。maxsize默認爲0
 
複製代碼
import queue
import time

q = queue.LifoQueue()

#LIFO隊列後進先出
q.put(2)
q.put(1)
q.put(3)

while not q.empty():
    next_item = q.get()
    print(next_item)
    time.sleep(1)

執行結果:
3
1
2
複製代碼

class queue.PriorityQueue(maxsize=0)

優先隊列,有別於普通隊列的先入先出(雖然字面上仍是隊列,但其實不管從含義仍是實現上,和普通隊列都有很大的區別),也有別於棧的先入後出。在實現上,它通常經過堆這一數據結構,而堆實際上是一種徹底二叉樹,它會對進入容器的元素進行排序(根據事先指定的規則),出隊的順序則會是二叉樹的根結點表明的元素。
複製代碼
from queue import PriorityQueue
import time

q = PriorityQueue()

q.put((2, 'code'))
q.put((1, 'eat'))
q.put((3, 'sleep'))

while not q.empty():
    next_item = q.get()
    print(next_item)
    time.sleep(3)

執行結果:
(1, 'eat')
(2, 'code')
(3, 'sleep')
複製代碼

exception queue.Empty

當Queue爲空時,非阻塞的get()或者get_nowait()被調用時,將拋出該異常。

exception queue.Full

當隊列滿時,非阻塞的put()或者put_nowait()被調用,將拋出該異常。

Queue對象(Queue、LifoQueue或者PriorityQueue)提供瞭如下方法:

Queue.qsize()

返回隊列的近似大小。注意,qsize() > 0並不能保證接下來的get()方法不被阻塞;一樣,qsize() < maxsize也不能保證put()將不被阻塞。
複製代碼
import queue
import time

q = queue.Queue()

q.put(2)
q.put(1)
q.put(3)
q.put('python')

print('queue long:%s'%q.qsize())

執行結果:
queue long:4
複製代碼

Queue.empty()
若是隊列是空的,則返回True,不然False。若是empty()返回True,並不能保證接下來的put()調用將不被阻塞。相似的,empty()返回False也不能保證接下來的get()調用將不被阻塞。

複製代碼
import queue

q = queue.Queue()
que = queue.Queue()

q.put(2)
q.put(1)
q.put(3)
q.put('python')

print('q is empty? :%s'%q.empty())
print('que is empty? :%s'%que.empty())
執行結果:
q is empty? :False    #隊列不爲空則返回False
que is empty? :True    #隊列未空則返回True
複製代碼

Queue.full()
若是隊列滿則返回True,不然返回False。若是full()返回True,並不能保證接下來的get()調用將不被阻塞。相似的,full()返回False也不能保證接下來的put()調用將不被阻塞。

複製代碼
import queue

q = queue.Queue(maxsize=4)
que = queue.Queue()

q.put(2)
q.put(1)
q.put(3)
q.put('python')

print('q is full? :%s'%q.full())
print('que is full? :%s'%que.full())
執行結果:
q is full? :True
que is full? :False
複製代碼

Queue.put(item, block=True, timeout=None)
放item到隊列中。若是block是True,且timeout是None,該方法將一直等待直到有隊列有空餘空間(默認block=True,timeout=None)。若是timeout是一個正整數,該方法則最多阻塞timeout秒並拋出Full異常。若是block是False而且隊列滿,則直接拋出Full異常(這時timeout將被忽略)。

block爲True

複製代碼
import queue
import time

q = queue.Queue(maxsize=2)

#將q隊列填滿
q.put('python')
q.put('linux')

print(time.ctime())    #打印當前時間
try:    #捕獲queue.Full異常
    #q.put('shell', timeout=3)    #默認block=True  
    #q.put('shell', True, timeout=3)    #能夠省略block=;直接寫True;timeout=能夠省略直接寫3
    q.put('shell', block=True, timeout=3)    #q隊列已滿,再次將數據放入q中,將阻塞3s後拋出異常queue.Full
except queue.Full:
    print('queue is full!')
    print(time.ctime())    #打印當前時間,可看出q隊列阻塞時長
執行結果:
Fri Nov  3 15:06:43 2017
queue is full!
Fri Nov  3 15:06:46 2017
複製代碼

block爲False

複製代碼
import queue
import time

q = queue.Queue(maxsize=2)

#將q隊列填滿
q.put('python')
q.put('linux')

print(time.ctime())    #打印當前時間
try:    #捕獲queue.Full異常
    q.put('shell', False, timeout=3)    #block爲False時,timeout失效會當即拋出queue.Full異常;故timeout選項能夠省略不寫
except queue.Full:
    print('queue is full!')
    print(time.ctime())    #打印當前時間,可看出q隊列阻塞時長

執行結果:
複製代碼

Queue.put_nowait(item)
等價於put(item, False)。

Queue.get(block=True, timeout=None)
從隊列中移除被返回一個條目。若是block是True而且timeout是None(默認block=True,timeout=None),該方法將阻塞直到隊列中有條目可用。若是timeout是正整數,該方法將最多阻塞timeout秒並拋出Empty異常。若是block是False而且隊列爲空,則直接拋出Empty異常(這時timeout將被忽略)。

block爲True

複製代碼
import queue
import time

q = queue.Queue(maxsize=2)

#當前q隊列填爲空
print(time.ctime())    #打印當前時間
try:    #捕獲queue.Empty異常
    q.get(True, 5)    #Queue.get()獲取數據阻塞5s
except queue.Empty:
    print('queue is empty!')
    print(time.ctime())    #打印當前時間,可看出q隊列阻塞時長
執行結果:
複製代碼

block爲False

複製代碼
import queue
import time

q = queue.Queue(maxsize=2)

#當前q隊列填爲空
print(time.ctime())    #打印當前時間
try:    #捕獲queue.Empty異常
    #q.get(False, 5)    #Queue.get()獲取數據阻塞5s,block=/timeout=能夠省略;block=False時timeout能夠省略
    q.get(False)
except queue.Empty:
    print('queue is empty!')
    print(time.ctime())    #打印當前時間,可看出q隊列阻塞時長
執行結果:
Fri Nov  3 15:38:23 2017
queue is empty!
Fri Nov  3 15:38:23 2017
複製代碼

Queue.get_nowait()
等價於get(False)。

Queue.task_done()
表示一個先前的隊列中的任務完成了。被隊列消費者線程使用。對於每一個get()獲取到的任務,接下來的task_done()的調用告訴隊列該任務的處理已經完成。
若是join()調用正在阻塞,當隊列中全部的條目被處理後它將恢復執行(意味着task_done()調用將被放入隊列中的每一個條目接收到)。
若是調用次數超過了隊列中放置的條目數目,將拋出ValueError異常。

Queue.join()

阻塞直到隊列中全部條目都被獲取並處理。
當一個條目被增長到隊列時,未完成任務的計數將增長。當一個消費者線程調用task_done()時,未完成任務的計數將減小。當未完成任務的計數減小到0時,join()解鎖。
複製代碼
#!/usr/bin/env python3

import queue
import time
import subprocess
import threading


q = queue.Queue()
hosts = ['192.168.1.68', '192.168.1.118', '192.168.1.101', '192.168.1.250', '192.168.1.133']

def run():
    while True:    #防止線程少於len(hosts)時卡死,不用while循環線程數少時就會致使隊列數據沒法所有取完,就會形成queue.join()一直阻塞狀態
        host = q.get()
        if host == '192.168.1.118':    #若是ip等於192.168.1.118就休眠10S,用於判讀queue.join()是否阻塞直到queue.task_doen()通知後接觸阻塞
            time.sleep(10)
        print('host ip is:%s'% host)
        q.task_done()    #當前線程任務完成

def main():
    for i in range(10):
        t = threading.Thread(target=run)
        t.setDaemon(True)
        t.start()

    for item in hosts:
        q.put(item)

    q.join()    #阻塞直至全部線程queue.task_done()返回  

start = time.time()
main()
print("Elapsed Time: %s" % (time.time() - start))
執行結果:
host ip is:192.168.88.68
host ip is:192.168.68.101
host ip is:192.168.66.250
host ip is:192.168.88.133
host ip is:192.168.88.118
Elapsed Time: 10.013836145401001    #因爲192.168.1.118大約阻塞了10S
複製代碼
相關文章
相關標籤/搜索