1. python隊列和列表區別
表就相當於一個有底的瓶子先進去的數據最後才出來。而隊列就相當於火車站排隊買票先進先出。並且只能從隊尾進對頭出
。
2. python fifo是什麼意思
FIFO,先進先出,計算機裡面,一般指的是隊列的性質。。
隊列是計算機軟體科學中,數據架構中的東西。。。
和python無關。。。
3. python 把列表當作隊列使用方法
5.1.2. 把列表當作隊列使用
你也可以把列表當作隊列使用,隊列作為特定的數據結構,最先進入的元素最先釋放(先進先出)。不過,列表這樣用效率不高。相對來說從列表末尾添加和彈出很快;在頭部插入和彈出很慢(因為,為了一個元素,要移動整個列表中的所有元素)。
要實現隊列,使用 collections.deque,它為在首尾兩端快速插入和刪除而設計。例如:
>>> from collections import deque
>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry") # Terry arrives
>>> queue.append("Graham") # Graham arrives
>>> queue.popleft() # The first to arrive now leaves
'Eric'
>>> queue.popleft() # The second to arrive now leaves
'John'
>>> queue # Remaining queue in order of arrival
deque(['Michael', 'Terry', 'Graham'])
4. python高並發怎麼解決
某個時間段內,數據涌來,這就是並發。如果數據量很大,就是高並發
高並發的解決方法:
1、隊列、緩沖區
假設只有一個窗口,陸續湧入食堂的人,排隊打菜是比較好的方式
所以,排隊(隊列)是一種天然解決並發的辦法
排隊就是把人排成 隊列,先進先出,解決了資源使用的問題
排成的隊列,其實就是一個緩沖地帶,就是 緩沖區
假設女生優先,每次都從這個隊伍中優先選出女生出來先打飯,這就是 優先隊列
例如queue模塊的類Queue、LifoQueue、PriorityQueue(小頂堆實現)
2、爭搶
只開一個窗口,有可能沒有秩序,也就是誰擠進去就給誰打飯
擠到窗口的人占據窗口,直到打到飯菜離開
其他人繼續爭搶,會有一個人占據著窗口,可以視為鎖定窗口,窗口就不能為其他人提供服務了。
這是一種鎖機制
誰搶到資源就上鎖,排他性的鎖,其他人只能等候
爭搶也是一種高並發解決方案,但是,這樣可能不好,因為有可能有人很長時間搶不到
3、預處理
如果排長隊的原因,是由於每個人打菜等候時間長,因為要吃的菜沒有,需要現做,沒打著飯不走開,鎖定著窗口
食堂可以提前統計大多數人最愛吃的菜品,將最愛吃的80%的熱門菜,提前做好,保證供應,20%的冷門菜,現做
這樣大多數人,就算鎖定窗口,也很快打到飯菜走了,快速釋放窗口
一種提前載入用戶需要的數據的思路,預處理 思想,緩存常用
更多Python知識,請關註:Python自學網!!
5. python分布式爬蟲是什麼意思
一、分布式爬蟲架構
在了解分布式爬蟲架構之前,首先回顧一下Scrapy的架構,如下圖所示。
我們需要做的就是在多台主機上同時運行爬蟲任務協同爬取,而協同爬取的前提就是共享爬取隊列。這樣各台主機就不需要各自維護爬取隊列,而是從共享爬取隊列存取Request。但是各台主機還是有各自的Scheler和Downloader,所以調度和下載功能分別完成。如果不考慮隊列存取性能消耗,爬取效率還是會成倍提高。
二、維護爬取隊列
那麼這個隊列用什麼來維護?首先需要考慮的就是性能問題。我們自然想到的是基於內存存儲的Redis,它支持多種數據結構,例如列表(List)、集合(Set)、有序集合(Sorted Set)等,存取的操作也非常簡單。
Redis支持的這幾種數據結構存儲各有優點。
列表有lpush()、lpop()、rpush()、rpop()方法,我們可以用它來實現先進先出式爬取隊列,也可以實現先進後出棧式爬取隊列。
集合的元素是無序的且不重復的,這樣我們可以非常方便地實現隨機排序且不重復的爬取隊列。
有序集合帶有分數表示,而Scrapy的Request也有優先順序的控制,我們可以用它來實現帶優先順序調度的隊列。
我們需要根據具體爬蟲的需求來靈活選擇不同的隊列。
三、如何去重
Scrapy有自動去重,它的去重使用了Python中的集合。這個集合記錄了Scrapy中每個Request的指紋,這個指紋實際上就是Request的散列值。我們可以看看Scrapy的源代碼,如下所示:
importhashlib
defrequest_fingerprint(request, include_headers=None):
ifinclude_headers:
include_headers = tuple(to_bytes(h.lower())
forhinsorted(include_headers))
cache = _fingerprint_cache.setdefault(request, {})
ifinclude_headersnotincache:
fp = hashlib.sha1()
fp.update(to_bytes(request.method))
fp.update(to_bytes(canonicalize_url(request.url)))
fp.update(request.bodyorb'')
ifinclude_headers:
forhdrininclude_headers:
ifhdrinrequest.headers:
fp.update(hdr)
forvinrequest.headers.getlist(hdr):
fp.update(v)
cache[include_headers] = fp.hexdigest()
returncache[include_headers]
request_fingerprint()就是計算Request指紋的方法,其方法內部使用的是hashlib的sha1()方法。計算的欄位包括Request的Method、URL、Body、Headers這幾部分內容,這里只要有一點不同,那麼計算的結果就不同。計算得到的結果是加密後的字元串,也就是指紋。每個Request都有獨有的指紋,指紋就是一個字元串,判定字元串是否重復比判定Request對象是否重復容易得多,所以指紋可以作為判定Request是否重復的依據。
那麼我們如何判定重復呢?Scrapy是這樣實現的,如下所示:
def__init__(self):
self.fingerprints = set()
defrequest_seen(self, request):
fp = self.request_fingerprint(request)
iffpinself.fingerprints:
returnTrue
self.fingerprints.add(fp)
在去重的類RFPDupeFilter中,有一個request_seen()方法,這個方法有一個參數request,它的作用就是檢測該Request對象是否重復。這個方法調用request_fingerprint()獲取該Request的指紋,檢測這個指紋是否存在於fingerprints變數中,而fingerprints是一個集合,集合的元素都是不重復的。如果指紋存在,那麼就返回True,說明該Request是重復的,否則這個指紋加入到集合中。如果下次還有相同的Request傳遞過來,指紋也是相同的,那麼這時指紋就已經存在於集合中,Request對象就會直接判定為重復。這樣去重的目的就實現了。
Scrapy的去重過程就是,利用集合元素的不重復特性來實現Request的去重。
對於分布式爬蟲來說,我們肯定不能再用每個爬蟲各自的集合來去重了。因為這樣還是每個主機單獨維護自己的集合,不能做到共享。多台主機如果生成了相同的Request,只能各自去重,各個主機之間就無法做到去重了。
那麼要實現去重,這個指紋集合也需要是共享的,Redis正好有集合的存儲數據結構,我們可以利用Redis的集合作為指紋集合,那麼這樣去重集合也是利用Redis共享的。每台主機新生成Request之後,把該Request的指紋與集合比對,如果指紋已經存在,說明該Request是重復的,否則將Request的指紋加入到這個集合中即可。利用同樣的原理不同的存儲結構我們也實現了分布式Reqeust的去重。
四、防止中斷
在Scrapy中,爬蟲運行時的Request隊列放在內存中。爬蟲運行中斷後,這個隊列的空間就被釋放,此隊列就被銷毀了。所以一旦爬蟲運行中斷,爬蟲再次運行就相當於全新的爬取過程。
要做到中斷後繼續爬取,我們可以將隊列中的Request保存起來,下次爬取直接讀取保存數據即可獲取上次爬取的隊列。我們在Scrapy中指定一個爬取隊列的存儲路徑即可,這個路徑使用JOB_DIR變數來標識,我們可以用如下命令來實現:
scrapy crawl spider -s JOB_DIR=crawls/spider
更加詳細的使用方法可以參見官方文檔,鏈接為:https://doc.scrapy.org/en/latest/topics/jobs.html。
在Scrapy中,我們實際是把爬取隊列保存到本地,第二次爬取直接讀取並恢復隊列即可。那麼在分布式架構中我們還用擔心這個問題嗎?不需要。因為爬取隊列本身就是用資料庫保存的,如果爬蟲中斷了,資料庫中的Request依然是存在的,下次啟動就會接著上次中斷的地方繼續爬取。
所以,當Redis的隊列為空時,爬蟲會重新爬取;當Redis的隊列不為空時,爬蟲便會接著上次中斷之處繼續爬取。
五、架構實現
我們接下來就需要在程序中實現這個架構了。首先實現一個共享的爬取隊列,還要實現去重的功能。另外,重寫一個Scheer的實現,使之可以從共享的爬取隊列存取Request。
幸運的是,已經有人實現了這些邏輯和架構,並發布成叫Scrapy-Redis的Python包。接下來,我們看看Scrapy-Redis的源碼實現,以及它的詳細工作原理
6. python中棧和隊列在功能上的區別
「棧」
和
「隊列」
是數據結構,與具體的語言無關。
1.隊列先進先出,棧先進後出。
2.
對插入和刪除操作的"限定"。
棧是限定只能在表的一端進行插入和刪除操作的線性表。
隊列是限定只能在表的一端進行插入和在另一端進行刪除操作的線性表。
從"數據結構"的角度看,它們都是線性結構,即數據元素之間的關系相同。但它們是完全不同的數據類型。除了它們各自的基本操作集不同外,主要區別是對插入和刪除操作的"限定"。
棧和隊列是在程序設計中被廣泛使用的兩種線性數據結構,它們的特點在於基本操作的特殊性,棧必須按"後進先出"的規則進行操作,而隊列必須按"先進先出"
的規則進行操作。和線性表相比,它們的插入和刪除操作受更多的約束和限定,故又稱為限定性的線性表結構。
3.遍歷數據速度不同。棧只能從頭部取數據
也就最先放入的需要遍歷整個棧最後才能取出來,而且在遍歷數據的時候還得為數據開辟臨時空間,保持數據在遍歷前的一致性隊列怎不同,他基於地址指針進行遍歷,而且可以從頭或尾部開始遍歷,但不能同時遍歷,無需開辟臨時空間,因為在遍歷的過程中不影像數據結構,速度要快的多
棧(stack)是限定只能在表的一端進行插入和刪除操作的線性表。
隊列(queue)是限定只能在表的一端進行插入和在另一端進行刪除操作的線性表。
從"數據結構"的角度看,它們都是線性結構,即數據元素之間的關系相同。但它們是完全不同的數據類型。除了它們各自的基本操作集不同外,主要區別是對插入和刪除操作的"限定"。
棧和隊列是在程序設計中被廣泛使用的兩種線性數據結構,它們的特點在於基本操作的特殊性,棧必須按"後進先出"的規則進行操作,而隊列必須按"先進先出"的規則進行操作。和線性表相比,它們的插入和刪除操作受更多的約束和限定,故又稱為限定性的線性表結構。
7. python queue是多線程么
是的。pythonqueue主要就是為多線程生產值、消費者之間線程通信提供服務,具有先進先出的數據結構。
8. PYTHON的數據結構和演算法介紹
當你聽到數據結構時,你會想到什麼?
數據結構是根據類型組織和分組數據的容器。它們基於可變性和順序而不同。可變性是指創建後改變對象的能力。我們有兩種類型的數據結構,內置數據結構和用戶定義的數據結構。
什麼是數據演算法-是由計算機執行的一系列步驟,接受輸入並將其轉換為目標輸出。
列表是用方括弧定義的,包含用逗號分隔的數據。該列表是可變的和有序的。它可以包含不同數據類型的混合。
months=['january','february','march','april','may','june','july','august','september','october','november','december']
print(months[0])#print the element with index 0
print(months[0:7])#all the elements from index 0 to 6
months[0]='birthday #exchange the value in index 0 with the word birthday
print(months)
元組是另一種容器。它是不可變有序元素序列的數據類型。不可變的,因為你不能從元組中添加和刪除元素,或者就地排序。
length, width, height =9,3,1 #We can assign multiple variables in one shot
print("The dimensions are {} * {} * {}".format(length, width, height))
一組
集合是唯一元素的可變且無序的集合。它可以讓我們快速地從列表中刪除重復項。
numbers=[1,2,3,4,6,3,3]
unique_nums = set(numbers)
print(unique_nums)
models ={'declan','gift','jabali','viola','kinya','nick',betty' }
print('davis' in models)#check if there is turner in the set models
models.add('davis')
print(model.pop())remove the last item#
字典
字典是可變和無序的數據結構。它允許存儲一對項目(即鍵和值)
下面的例子顯示了將容器包含到其他容器中來創建復合數據結構的可能性。
* 用戶定義的數據結構*
使用數組的堆棧堆棧是一種線性數據結構,其中元素按順序排列。它遵循L.I.F.O的機制,意思是後進先出。因此,最後插入的元素將作為第一個元素被刪除。這些操作是:
溢出情況——當我們試圖在一個已經有最大元素的堆棧中再放一個元素時,就會出現這種情況。
下溢情況——當我們試圖從一個空堆棧中刪除一個元素時,就會出現這種情況。
隊列是一種線性數據結構,其中的元素按順序排列。它遵循先進先出的F.I.F.O機制。
描述隊列特徵的方面
兩端:
前端-指向起始元素。
指向最後一個元素。
有兩種操作:
樹用於定義層次結構。它從根節點開始,再往下,最後的節點稱為子節點。
鏈表
它是具有一系列連接節點的線性數據。每個節點存儲數據並顯示到下一個節點的路由。它們用來實現撤銷功能和動態內存分配。
圖表
這是一種數據結構,它收集了具有連接到其他節點的數據的節點。
它包括:
演算法
在演算法方面,我不會講得太深,只是陳述方法和類型:
原文:https://www.tuicool.com/articles/hit/VRRvYr3
9. Python中 socket 和 Queue有什麼區別
socket(計算機專業術語):網路上的兩個程序通過一個雙向的通信連接實現數據的交換,這個連接的一端稱為一個socket。建立網路通信連接至少要一對埠號(socket)。socket本質是編程介面(API),對TCP/IP的封裝,TCP/IP也要提供可供程序員做網路開發所用的介面,這就是Socket編程介面;HTTP是轎車,提供了封裝或者顯示數據的具體形式;Socket是發動機,提供了網路通信的能力。
queue(線性表):隊列是一種特殊的線性表,是一種先進先出(FIFO)的數據結構。它只允許在表的前端(front)進行刪除操作,而在表的後端(rear)進行插入操作。進行插入操作的端稱為隊尾,進行刪除操作的端稱為隊頭。隊列中沒有元素時,稱為空隊列。而其在C++中的應用語法:queue類是為程序員提供了一個隊列的功能的容器適配器,具體而言,一個FIFO(先入先出)的數據結構;在頭文件<queue>中定義(在程序開頭輸入#include <queue>,切記不可寫為#include <queue.h>)。
望採納