❶ Elasticsearch性能優化
註:文本整理自《ELKstack權威指南》
在 CRUD 章節,我們已經知道 ES 的數據寫入是如何操作的了。喜歡自己動手的讀者可能已經迫不及待的自己寫了程序開始往 ES 里寫數據做測試。這時候大家會發現:程序的運行速度非常一般,即使 ES 服務運行在本機,一秒鍾大概也就能寫入幾百條數據。
這種速度顯然不是 ES 的極限。事實上,每條數據經過一次完整的 HTTP POST 請求和 ES indexing 是一種極大的性能浪費,為此,ES 設計了批量提交方式。在數據讀取方面,叫 mget 介面,在數據變更方面,叫 bulk 介面。mget 一般常用於搜索時 ES 節點之間批量獲取中間結果集,對於 Elastic Stack 用戶,更常見到的是 bulk 介面。
bulk 介面採用一種比較簡朴的數據積累格式,示例如下:
格式是,每條 JSON 數據的上面,加一行描述性的元 JSON,指明下一行數據的操作類型,歸屬索引信息等。
採用這種格式,而不是一般的 JSON 數組格式,是因為接收到 bulk 請求的 ES 節點,就可以不需要做完整的 JSON 數組解析處理,直接按行處理簡短的元 JSON,就可以確定下一行數據 JSON 轉發給哪個數據節點了。這樣,一個固定內存大小的 network buffer 空間,就可以反復使用,又節省了大量 JVM 的 GC。
事實上,產品級的 logstash、rsyslog、spark 都是默認採用 bulk 介面進行數據寫入的。對於打算自己寫程序的讀者,建議採用 Perl 的 Search::Elasticsearch::Bulk 或者 python 的 elasticsearch.helpers.* 庫。
在配置 bulk 數據的時候,一般需要注意的就是請求體大小(bulk size)。
這里有一點細節上的矛盾,我們知道,HTTP 請求,是可以通過 HTTP 狀態碼 100 Continue 來持續發送數據的。但對於 ES 節點接收 HTTP 請求體的 Content-Length 來說,是按照整個大小來計算的。所以,首先,要確保 bulk 數據不要超過 http.max_content_length 設置。
那麼,是不是盡量讓 bulk size 接近這個數值呢?當然不是。
依然是請求體的問題,因為請求體需要全部載入到內存,而 JVM Heap 一共就那麼多(按 31GB 算),過大的請求體,會擠占其他線程池的空間,反而導致寫入性能的下降。
再考慮網卡流量,磁碟轉速的問題,所以一般來說,建議 bulk 請求體的大小,在 15MB 左右,通過實際測試繼續向上探索最合適的設置。
注意:這里說的 15MB 是請求體的位元組數,而不是程序里里設置的 bulk size。bulk size 一般指數據的條目數。不要忘了,bulk 請求體中,每條數據還會額外帶上一行元 JSON。
以 logstash 默認的 bulk_size => 5000 為例,假設單條數據平均大小 200B ,一次 bulk 請求體的大小就是 1.5MB。那麼我們可以嘗試 bulk_size => 50000 ;而如果單條數據平均大小是 20KB,一次 bulk 大小就是 100MB,顯然超標了,需要嘗試下調至 bulk_size => 500 。
gateway 是 ES 設計用來長期存儲索引數據的介面。一般來說,大家都是用本地磁碟來存儲索引數據,即 gateway.type 為 local 。
數據恢復中,有很多策略調整我們已經在之前分片控制小節講過。除開分片級別的控制以外,gateway 級別也還有一些可優化的地方:
注意:gateway 中說的節點,僅包括主節點和數據節點,純粹的 client 節點是不算在內的。如果你有更明確的選擇,也可以按需求寫:
雖然 ES 對 gateway 使用 NFS,iscsi 等共享存儲的方式極力反對,但是對於較大量級的索引的副本數據,ES 從 1.5 版本開始,還是提供了一種節約成本又不特別影響性能的方式:影子副本(shadow replica)。
首先,需要在集群各節點的 elasticsearch.yml 中開啟選項:
同時,確保各節點使用相同的路徑掛載了共享存儲,且目錄許可權為 Elasticsearch 進程用戶可讀可寫。
然後,創建索引:
針對 shadow replicas ,ES 節點不會做實際的索引操作,而是單純的每次 flush 時,把 segment 內容 fsync 到共享存儲磁碟上。然後 refresh 讓其他節點能夠搜索該 segment 內容。
如果你已經決定把數據放到共享存儲上了,採用 shadow replicas 還是有一些好處的:
但是請注意:主分片節點還是要承擔一個副本的寫入過程,並不像 Lucene 的 FileReplicator 那樣通過復制文件完成,所以達不到完全節省 CPU 的效果。
shadow replicas 只是一個在某些特定環境下有用的方式。在資源允許的情況下,還是應該使用 local gateway。而另外採用 snapshot 介面來完成數據長期備份到 HDFS 或其他共享存儲的需要。
我們都知道,ES 中的 master 跟一般 MySQL、Hadoop 的 master 是不一樣的。它即不是寫入流量的唯一入口,也不是所有數據的元信息的存放地點。所以,一般來說,ES 的 master 節點負載很輕,集群性能是可以近似認為隨著 data 節點的擴展線性提升的。
但是,上面這句話並不是完全正確的。
ES 中有一件事情是只有 master 節點能管理的,這就是集群狀態(cluster state)。
集群狀態中包括以下信息:
這些信息在集群的任意節點上都存放著,你也可以通過 /_cluster/state 介面直接讀取到其內容。注意這最後一項信息,之前我們已經講過 ES 怎麼通過簡單地取余知道一條數據放在哪個分片里,加上現在集群狀態里又記載了分片在哪個節點上,那麼,整個集群里,任意節點都可以知道一條數據在哪個節點上存儲了。所以,數據讀寫才可以發送給集群里任意節點。
至於修改,則只能由 master 節點完成!顯然,集群狀態里大部分內容是極少變動的,唯獨有一樣除外——索引的映射。因為 ES 的 schema-less 特性,我們可以任意寫入 JSON 數據,所以索引中隨時可能增加新的欄位。這個時候,負責容納這條數據的主分片所在的節點,會暫停寫入操作,將欄位的映射結果傳遞給 master 節點;master 節點合並這段修改到集群狀態里,發送新版本的集群狀態到集群的所有節點上。然後寫入操作才會繼續。一般來說,這個操作是在一二十毫秒內就可以完成,影響也不大。
但是也有一些情況會是例外。
在較大規模的 Elastic Stack 應用場景中,這是比較常見的一個情況。因為 Elastic Stack 建議採用日期時間作為索引的劃分方式,所以定時(一般是每天),會統一產生一批新的索引。而前面已經講過,ES 的集群狀態每次更新都是阻塞式的發布到全部節點上以後,節點才能繼續後續處理。
這就意味著,如果在集群負載較高的時候,批量新建新索引,可能會有一個顯著的阻塞時間,無法寫入任何數據。要等到全部節點同步完成集群狀態以後,數據寫入才能恢復。
不巧的是,中國使用的是北京時間,UTC +0800。也就是說,默認的 Elastic Stack 新建索引時間是在早上 8 點。這個時間點一般日誌寫入量已經上漲到一定水平了(當然,晚上 0 點的量其實也不低)。
對此,可以通過定時任務,每天在最低谷的早上三四點,提前通過 POST mapping 的方式,創建好之後幾天的索引。就可以避免這個問題了。
如果你的日誌是比較嚴重的非結構化數據,這個問題在 2.0 版本後會變得更加嚴重。 Elasticsearch 從 2.0 版本開始,對 mapping 更新做了重構。為了防止欄位類型沖突和減少 master 定期下發全量 cluster state 導致的大流量壓力,新的實現和舊實現的區別在:
也就是說,一旦你日誌中欄位數量較多,在新創建索引的一段時間內,可能長達幾十分鍾一直被反復鎖死!
這是另一種常見的濫用。在使用 Elastic Stack 處理訪問日誌時,為了查詢更方便,可能會採用 logstash-filter-kv 插件,將訪問日誌中的每個 URL 參數,都切分成單獨的欄位。比如一個 "/index.do?uid=1234567890&action=payload" 的 URL 會被轉換成如下 JSON:
但是,因為集群狀態是存在所有節點的內存里的,一旦 URL 參數過多,ES 節點的內存就被大量用於存儲欄位映射內容。這是一個極大的浪費。如果碰上 URL 參數的鍵內容本身一直在變動,直接撐爆 ES 內存都是有可能的!
以上是真實發生的事件,開發人員莫名的選擇將一個 UUID 結果作為 key 放在 URL 參數里。直接導致 ES 集群 master 節點全部 OOM。
如果你在 ES 日誌中一直看到有新的 updating mapping [logstash-2015.06.01] 字樣出現的話,請鄭重考慮一下自己是不是用的上如此細分的欄位列表吧。
好,三秒鍾過去,如果你確定一定以及肯定還要這么做,下面是一個變通的解決辦法。
用 nested object 來存放 URL 參數的方法稍微復雜,但還可以接受。單從 JSON 數據層面看,新方式的數據結構如下:
沒錯,看起來就是一個數組。但是 JSON 數組在 ES 里是有兩種處理方式的。
如果直接寫入數組,ES 在實際索引過程中,會把所有內容都平鋪開,變成 Arrays of Inner Objects 。整條數據實際類似這樣的結構:
這種方式最大的問題是,當你採用 urlargs.key:"uid" AND urlargs.value:"0987654321" 語句意圖搜索一個 uid=0987654321 的請求時,實際是整個 URL 參數中任意一處 value 為 0987654321 的,都會命中。
要想達到正確搜索的目的,需要在寫入數據之前,指定 urlargs 欄位的映射類型為 nested object。命令如下:
這樣,數據實際是類似這樣的結構:
當然,nested object 節省欄位映射的優勢對應的是它在使用的復雜。Query 和 Aggs 都必須使用專門的 nested query 和 nested aggs 才能正確讀取到它。
nested query 語法如下:
nested aggs 語法如下:
ES 內針對不同階段,設計有不同的緩存。以此提升數據檢索時的響應性能。主要包括節點層面的 filter cache 和分片層面的 request cache。下面分別講述。
ES 的 query DSL 在 2.0 版本之前分為 query 和 filter 兩種,很多檢索語法,是同時存在 query 和 filter 里的。比如最常用的 term、prefix、range 等。怎麼選擇是使用 query 還是 filter 成為很多用戶頭疼的難題。於是從 2.0 版本開始,ES 乾脆合並了 filter 統一歸為 query。但是具體的檢索語法本身,依然有 query 和 filter 上下文的區別。ES 依靠這個上下文判斷,來自動決定是否啟用 filter cache。
query 跟 filter 上下文的區別,簡單來說:
所以,選擇也就出來了:
不過我們要怎麼寫,才能讓 ES 正確判斷呢?看下面這個請求:
在這個請求中,
需要注意的是,filter cache 是節點層面的緩存設置,每個節點上所有數據在響應請求時,是共用一個緩存空間的。當空間用滿,按照 LRU 策略淘汰掉最冷的數據。
可以用 indices.cache.filter.size 配置來設置這個緩存空間的大小,默認是 JVM 堆的 10%,也可以設置一個絕對值。注意這是一個靜態值,必須在 elasticsearch.yml 中提前配置。
ES 還有另一個分片層面的緩存,叫 shard request cache。5.0 之前的版本中,request cache 的用途並不大,因為 query cache 要起作用,還有幾個先決條件:
以 Elastic Stack 場景來說,Kibana 里幾乎所有的請求,都是有 @timestamp 作為過濾條件的,而且大多數是以 最近 N 小時/分鍾 這樣的選項,也就是說,頁面每次刷新,發出的請求 JSON 里的時間過濾部分都是在變動的。query cache 在處理 Kibana 發出的請求時,完全無用。
而 5.0 版本的一大特性,叫 instant aggregation。解決了這個先決條件的一大阻礙。
在之前的版本,Elasticsearch 接收到請求之後,直接把請求原樣轉發給各分片,由各分片所在的節點自行完成請求的解析,進行實際的搜索操作。所以緩存的鍵是原始 JSON 串。
而 5.0 的重構後,接收到請求的節點先把請求的解析做完,發送到各節點的是統一拆分修改好的請求,這樣就不再擔心 JSON 串多個空格啥的了。
其次,上面說的『拆分修改』是怎麼回事呢?
比如,我們在 Kibana 里搜索一個最近 7 天( @timestamp:["now-7d" TO "now"] )的數據,ES 就可以根據按天索引的判斷,知道從 6 天前到昨天這 5 個索引是肯定全覆蓋的。那麼這個橫跨 7 天的 date range query 就變成了 5 個 match_all query 加 2 個短時間的 date_range query。
現在你的儀表盤過 5 分鍾自動刷新一次,再提交上來一次最近 7 天的請求,中間這 5 個 match_all 就完全一樣了,直接從 request cache 返回即可,需要重新請求的,只有兩頭真正在變動的 date_range 了。
注1: match_all 不用遍歷倒排索引,比直接查詢 @timestamp:* 要快很多。
注2:判斷覆蓋修改為 match_all 並不是真的按照索引名稱,而是 ES 從 2.x 開始提供的 field_stats 介面可以直接獲取到 @timestamp 在本索引內的 max/min 值。當然從概念上如此理解也是可以接受的。
響應結果如下:
和 filter cache 一樣,request cache 的大小也是以節點級別控制的,配置項名為 indices.requests.cache.size ,其默認值為 1% 。
欄位數據(fielddata),在 Lucene 中又叫 uninverted index。我們都知道,搜索引擎會使用倒排索引(inverted index)來映射單詞到文檔的 ID 號。而同時,為了提供對文檔內容的聚合,Lucene 還可以在運行時將每個欄位的單詞以字典序排成另一個 uninverted index,可以大大加速計算性能。
作為一個加速性能的方式,fielddata 當然是被全部載入在內存的時候最為有效。這也是 ES 默認的運行設置。但是,內存是有限的,所以 ES 同時也需要提供對 fielddata 內存的限額方式:
Elasticsearch 在 total,fielddata,request 三個層面上都設計有 circuit breaker 以保護進程不至於發生 OOM 事件。在 fielddata 層面,其設置為:
但是相比較集群龐大的數據量,內存本身是遠遠不夠的。為了解決這個問題,ES 引入了另一個特性,可以對精確索引的欄位,指定 fielddata 的存儲方式。這個配置項叫: doc_values 。
所謂 doc_values ,其實就是在 ES 將數據寫入索引的時候,提前生成好 fielddata 內容,並記錄到磁碟上。因為 fielddata 數據是順序讀寫的,所以即使在磁碟上,通過文件系統層的緩存,也可以獲得相當不錯的性能。
注意:因為 doc_values 是在數據寫入時即生成內容,所以,它只能應用在精準索引的欄位上,因為索引進程沒法知道後續會有什麼分詞器生成的結果。
由於在 Elastic Stack 場景中, doc_values 的使用極其頻繁,到 Elasticsearch 5.0 以後,這兩者的區別被徹底強化成兩個不同欄位類型: text 和 keyword 。
等同於過去的:
而
等同於過去的:
也就是說,以後的用戶,已經不太需要在意 fielddata 的問題了。不過依然有少數情況,你會需要對分詞欄位做聚合統計的話,你可以在自己接受范圍內,開啟這個特性:
你可以看到在上面加了一段 fielddata_frequency_filter 配置,這個配置是 segment 級別的。上面示例的意思是:只有這個 segment 里的文檔數量超過 500 個,而且含有該欄位的文檔數量占該 segment 里的文檔數量比例超過 10% 時,才載入這個 segment 的 fielddata。
下面是一個可能有用的對分詞欄位做聚合的示例:
這個示例可以對經過了 logstash-filter-punct 插件處理的數據,獲取每種 punct 類型日誌的關鍵詞和對應的代表性日誌原文。其效果類似 Splunk 的事件模式功能:
[圖片上傳失敗...(image-b0b69f-1511752650964)]
如果經過之前章節的一系列優化之後,數據確實超過了集群能承載的能力,除了拆分集群以外,最後就只剩下一個辦法了:清除廢舊索引。
為了更加方便的做清除數據,合並 segment,備份恢復等管理任務,Elasticsearch 在提供相關 API 的同時,另外准備了一個命令行工具,叫 curator 。curator 是 Python 程序,可以直接通過 pypi 庫安裝:
注意,是 elasticsearch-curator 不是 curator。PyPi 原先就有另一個項目叫這個名字
和 Elastic Stack 里其他組件一樣,curator 也是被 Elastic.co 收購的原開源社區周邊。收編之後同樣進行了一次重構,命令行參數從單字母風格改成了長單詞風格。新版本的 curator 命令可用參數如下:
Options 包括:
--host TEXT Elasticsearch host.
--url_prefix TEXT Elasticsearch http url prefix.
--port INTEGER Elasticsearch port.
--use_ssl Connect to Elasticsearch through SSL.
--http_auth TEXT Use Basic Authentication ex: user:pass
--timeout INTEGER Connection timeout in seconds.
--master-only Only operate on elected master node.
--dry-run Do not perform any changes.
--debug Debug mode
--loglevel TEXT Log level
--logfile TEXT log file
--logformat TEXT Log output format [default|logstash].
--version Show the version and exit.
--help Show this message and exit.
Commands 包括:
alias Index Aliasing
allocation Index Allocation
bloom Disable bloom filter cache
close Close indices
delete Delete indices or snapshots
open Open indices
optimize Optimize Indices
replicas Replica Count Per-shard
show Show indices or snapshots
snapshot Take snapshots of indices (Backup)
針對具體的 Command,還可以繼續使用 --help 查看該子命令的幫助。比如查看 close 子命令的幫助,輸入 curator close --help ,結果如下:
在使用 1.4.0 以上版本的 Elasticsearch 前提下,curator 曾經主要的一個子命令 bloom 已經不再需要使用。所以,目前最常用的三個子命令,分別是 close , delete 和 optimize ,示例如下:
這一頓任務,結果是:
logstash-mweibo-nginx-yyyy.mm.dd 索引保存最近 5 天, logstash-mweibo-client-yyyy.mm.dd 保存最近 10 天, logstash-mweibo-yyyy.mm.dd 索引保存最近 30 天;且所有七天前的 logstash-* 索引都暫時關閉不用;最後對所有非當日日誌做 segment 合並優化。
profiler 是 Elasticsearch 5.0 的一個新介面。通過這個功能,可以看到一個搜索聚合請求,是如何拆分成底層的 Lucene 請求,並且顯示每部分的耗時情況。
啟用 profiler 的方式很簡單,直接在請求里加一行即可:
可以看到其中對 query 和 aggs 部分的返回是不太一樣的。
query 部分包括 collectors、rewrite 和 query 部分。對復雜 query,profiler 會拆分 query 成多個基礎的 TermQuery,然後每個 TermQuery 再顯示各自的分階段耗時如下:
我們可以很明顯的看到聚合統計在初始化階段、收集階段、構建階段、匯總階段分別花了多少時間,遍歷了多少數據。
注意其中 rece 階段還沒實現完畢,所有都是 0。因為目前 profiler 只能在 shard 級別上做統計。
collect 階段的耗時,有助於我們調整對應 aggs 的 collect_mode 參數選擇。目前 Elasticsearch 支持 breadth_first 和 depth_first 兩種方式。
initialise 階段的耗時,有助於我們調整對應 aggs 的 execution_hint 參數選擇。目前 Elasticsearch 支持 map 、 global_ordinals_low_cardinality 、 global_ordinals 和 global_ordinals_hash 四種選擇。在計算離散度比較大的欄位統計值時,適當調整該參數,有益於節省內存和提高計算速度。
對高離散度欄位值統計性能很關注的讀者,可以關注 https://github.com/elastic/elasticsearch/pull/21626 這條記錄的進展。
(本文完)
文本整理自《ELKstack權威指南》
❷ python 基礎教程
運算
a = 21
b = 10
c = 0
c = a + b
print "1 - c 的值為:", c
c = a - b
print "2 - c 的值為:", c
c = a * b
print "3 - c 的值為:", c
c = a / b
print "4 - c 的值為:", c
c = a % b
print "5 - c 的值為:", c
a = 2
b = 3
c = a**b
print "6 - c 的值為:", c
a = 10
b = 5
c = a//b
print "7 - c 的值為:", c
python比較
a = 21
b = 10
c = 0
if ( a == b ):
print "1 - a 等於 b"
else:
print "1 - a 不等於 b"
if ( a != b ):
print "2 - a 不等於 b"
else:
print "2 - a 等於 b"
if ( a <> b ):
print "3 - a 不等於 b"
else:
print "3 - a 等於 b"
if ( a < b ):
print "4 - a 小於 b"
else:
print "4 - a 大於等於 b"
if ( a > b ):
print "5 - a 大於 b"
else:
print "5 - a 小於等於 b"
a = 5
b = 20
if ( a <= b ):
print "6 - a 小於等於 b"
else:
print "6 - a 大於 b"
if ( b >= a ):
print "7 - b 大於等於 a"
else:
print "7 - b 小於 a"
賦值
a = 21
b = 10
c = 0
c = a + b
print "1 - c 的值為:", c
c += a
print "2 - c 的值為:", c
c *= a
print "3 - c 的值為:", c
c /= a
print "4 - c 的值為:", c
c = 2
c %= a
print "5 - c 的值為:", c
c **= a
print "6 - c 的值為:", c
c //= a
print "7 - c 的值為:", c
邏輯運算符:
a = 10
b = 20
if ( a and b ):
print "1 - 變數 a 和 b 都為 true"
else:
print "1 - 變數 a 和 b 有一個不為 true"
if ( a or b ):
print "2 - 變數 a 和 b 都為 true,或其中一個變數為 true"
else:
print "2 - 變數 a 和 b 都不為 true"
a = 0
if ( a and b ):
print "3 - 變數 a 和 b 都為 true"
else:
print "3 - 變數 a 和 b 有一個不為 true"
if ( a or b ):
print "4 - 變數 a 和 b 都為 true,或其中一個變數為 true"
else:
print "4 - 變數 a 和 b 都不為 true"
if not( a and b ):
print "5 - 變數 a 和 b 都為 false,或其中一個變數為 false"
else:
print "5 - 變數 a 和 b 都為 true"
in,not in
a = 10
b = 20
list = [1, 2, 3, 4, 5 ];
if ( a in list ):
print "1 - 變數 a 在給定的列表中 list 中"
else:
print "1 - 變數 a 不在給定的列表中 list 中"
if ( b not in list ):
print "2 - 變數 b 不在給定的列表中 list 中"
else:
print "2 - 變數 b 在給定的列表中 list 中"
a = 2
if ( a in list ):
print "3 - 變數 a 在給定的列表中 list 中"
else:
print "3 - 變數 a 不在給定的列表中 list 中"
條件
flag = False
name = 'luren'
if name == 'python': # 判斷變數否為'python'
flag = True # 條件成立時設置標志為真
print 'welcome boss' # 並輸出歡迎信息
else:
print name
num = 5
if num == 3: # 判斷num的值
print 'boss'
elif num == 2:
print 'user'
elif num == 1:
print 'worker'
elif num < 0: # 值小於零時輸出
print 'error'
else:
print 'roadman' # 條件均不成立時輸出
循環語句:
count = 0
while (count < 9):
print 'The count is:', count
count = count + 1
print "Good bye!"
i = 1
while i < 10:
i += 1
if i%2 > 0: # 非雙數時跳過輸出
continue
print i # 輸出雙數2、4、6、8、10
i = 1
while 1: # 循環條件為1必定成立
print i # 輸出1~10
i += 1
if i > 10: # 當i大於10時跳出循環
break
for letter in 'Python': # 第一個實例
print '當前字母 :', letter
fruits = ['banana', 'apple', 'mango']
for fruit in fruits: # 第二個實例
print '當前水果 :', fruit
print "Good bye!"
獲取用戶輸入:raw_input
var = 1
while var == 1 : # 該條件永遠為true,循環將無限執行下去
num = raw_input("Enter a number :")
print "You entered: ", num
print "Good bye!"
range,len
fruits = ['banana', 'apple', 'mango']
for index in range(len(fruits)):
print '當前水果 :', fruits[index]
print "Good bye!"
python數學函數:
abs,cell,cmp,exp,fabs,floor,log,log10,max,min,mod,pow,round,sqrt
randrange
訪問字元串的值
var1 = 'Hello World!'
var2 = "Python Runoob"
print "var1[0]: ", var1[0]
print "var2[1:5]: ", var2[1:5]
轉義字元
格式化輸出
print "My name is %s and weight is %d kg!" % ('Zara', 21)
字元串函數:
添加元素
list = [] ## 空列表
list.append('Google') ## 使用 append() 添加元素
list.append('Runoob')
print list
刪除元素
list1 = ['physics', 'chemistry', 1997, 2000]
print list1
del list1[2]
print "After deleting value at index 2 : "
print list1
列表操作
列表方法
刪除字典
dict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'};
del dict['Name']; # 刪除鍵是'Name'的條目
dict.clear(); # 清空詞典所有條目
del dict ; # 刪除詞典
print "dict['Age']: ", dict['Age'];
print "dict['School']: ", dict['School'];
字典的函數:
當前時間戳:
import time
time.time()
格式化日期輸出
import time
print time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print time.strftime("%a %b %d %H:%M:%S %Y", time.localtime())
a = "Sat Mar 28 22:24:24 2016"
print time.mktime(time.strptime(a,"%a %b %d %H:%M:%S %Y"))
獲取某個月日歷:calendar
import calendar
cal = calendar.month(2016, 1)
print "以下輸出2016年1月份的日歷:"
print cal
當前日期和時間
import datetime
i = datetime.datetime.now()
print ("當前的日期和時間是 %s" % i)
print ("ISO格式的日期和時間是 %s" % i.isoformat() )
print ("當前的年份是 %s" %i.year)
print ("當前的月份是 %s" %i.month)
print ("當前的日期是 %s" %i.day)
print ("dd/mm/yyyy 格式是 %s/%s/%s" % (i.day, i.month, i.year) )
print ("當前小時是 %s" %i.hour)
print ("當前分鍾是 %s" %i.minute)
print ("當前秒是 %s" %i.second)
不定長參數:*
lambda:匿名函數
def....
python模塊搜索路徑
獲取用戶輸入
str = raw_input("請輸入:")
print "你輸入的內容是: ", str
input可以接收表達式
open參數
write要自己添加換行符
讀取10個字元
重命名:os.rename
os.remove
os.mkdir os.chdir
os.getcwd
os.rmdir
open參數
file的方法
異常:
try:
fh = open("testfile", "w")
fh.write("這是一個測試文件,用於測試異常!!")
except IOError:
print "Error: 沒有找到文件或讀取文件失敗"
else:
print "內容寫入文件成功"
fh.close()
try:
fh = open("testfile", "w")
fh.write("這是一個測試文件,用於測試異常!!")
finally:
print "Error: 沒有找到文件或讀取文件失敗"
用戶自定義異常:
os 模塊提供了非常豐富的方法用來處理文件和目錄。常用的方法如下表所示:
| 序號 | 方法及描述 |
| 1 |
os.access(path, mode)
檢驗許可權模式 |
| 2 |
os.chdir(path)
改變當前工作目錄 |
| 3 |
os.chflags(path, flags)
設置路徑的標記為數字標記。 |
| 4 |
os.chmod(path, mode)
更改許可權 |
| 5 |
os.chown(path, uid, gid)
更改文件所有者 |
| 6 |
os.chroot(path)
改變當前進程的根目錄 |
| 7 |
os.close(fd)
關閉文件描述符 fd |
| 8 |
os.closerange(fd_low, fd_high)
關閉所有文件描述符,從 fd_low (包含) 到 fd_high (不包含), 錯誤會忽略 |
| 9 |
os.p(fd)
復制文件描述符 fd |
| 10 |
os.p2(fd, fd2)
將一個文件描述符 fd 復制到另一個 fd2 |
| 11 |
os.fchdir(fd)
通過文件描述符改變當前工作目錄 |
| 12 |
os.fchmod(fd, mode)
改變一個文件的訪問許可權,該文件由參數fd指定,參數mode是Unix下的文件訪問許可權。 |
| 13 |
os.fchown(fd, uid, gid)
修改一個文件的所有權,這個函數修改一個文件的用戶ID和用戶組ID,該文件由文件描述符fd指定。 |
| 14 |
os.fdatasync(fd)
強制將文件寫入磁碟,該文件由文件描述符fd指定,但是不強制更新文件的狀態信息。 |
| 15 |
os.fdopen(fd[, mode[, bufsize]])
通過文件描述符 fd 創建一個文件對象,並返回這個文件對象 |
| 16 |
os.fpathconf(fd, name)
返回一個打開的文件的系統配置信息。name為檢索的系統配置的值,它也許是一個定義系統值的字元串,這些名字在很多標准中指定(POSIX.1, Unix 95, Unix 98, 和其它)。 |
| 17 |
os.fstat(fd)
返迴文件描述符fd的狀態,像stat()。 |
| 18 |
os.fstatvfs(fd)
返回包含文件描述符fd的文件的文件系統的信息,像 statvfs() |
| 19 |
os.fsync(fd)
強制將文件描述符為fd的文件寫入硬碟。 |
| 20 |
os.ftruncate(fd, length)
裁剪文件描述符fd對應的文件, 所以它最大不能超過文件大小。 |
| 21 |
os.getcwd()
返回當前工作目錄 |
| 22 |
os.getcw()
返回一個當前工作目錄的Unicode對象 |
| 23 |
os.isatty(fd)
如果文件描述符fd是打開的,同時與tty(-like)設備相連,則返回true, 否則False。 |
| 24 |
os.lchflags(path, flags)
設置路徑的標記為數字標記,類似 chflags(),但是沒有軟鏈接 |
| 25 |
os.lchmod(path, mode)
修改連接文件許可權 |
| 26 |
os.lchown(path, uid, gid)
更改文件所有者,類似 chown,但是不追蹤鏈接。 |
| 27 |
os.link(src, dst)
創建硬鏈接,名為參數 dst,指向參數 src |
| 28 |
os.listdir(path)
返回path指定的文件夾包含的文件或文件夾的名字的列表。 |
| 29 |
os.lseek(fd, pos, how)
設置文件描述符 fd當前位置為pos, how方式修改: SEEK_SET 或者 0 設置從文件開始的計算的pos; SEEK_CUR或者 1 則從當前位置計算; os.SEEK_END或者2則從文件尾部開始. 在unix,Windows中有效 |
| 30 |
os.lstat(path)
像stat(),但是沒有軟鏈接 |
| 31 |
os.major(device)
從原始的設備號中提取設備major號碼 (使用stat中的st_dev或者st_rdev field)。 |
| 32 |
os.makedev(major, minor)
以major和minor設備號組成一個原始設備號 |
| 33 |
os.makedirs(path[, mode])
遞歸文件夾創建函數。像mkdir(), 但創建的所有intermediate-level文件夾需要包含子文件夾。 |
| 34 |
os.minor(device)
從原始的設備號中提取設備minor號碼 (使用stat中的st_dev或者st_rdev field )。 |
| 35 |
os.mkdir(path[, mode])
以數字mode的mode創建一個名為path的文件夾.默認的 mode 是 0777 (八進制)。 |
| 36 |
os.mkfifo(path[, mode])
創建命名管道,mode 為數字,默認為 0666 (八進制) |
| 37 |
os.mknod(filename[, mode=0600, device])
創建一個名為filename文件系統節點(文件,設備特別文件或者命名pipe)。
|
| 38 |
os.open(file, flags[, mode])
打開一個文件,並且設置需要的打開選項,mode參數是可選的 |
| 39 |
os.openpty()
打開一個新的偽終端對。返回 pty 和 tty的文件描述符。 |
| 40 |
os.pathconf(path, name)
返回相關文件的系統配置信息。 |
| 41 |
os.pipe()
創建一個管道. 返回一對文件描述符(r, w) 分別為讀和寫 |
| 42 |
os.popen(command[, mode[, bufsize]])
從一個 command 打開一個管道 |
| 43 |
os.read(fd, n)
從文件描述符 fd 中讀取最多 n 個位元組,返回包含讀取位元組的字元串,文件描述符 fd對應文件已達到結尾, 返回一個空字元串。 |
| 44 |
os.readlink(path)
返回軟鏈接所指向的文件 |
| 45 |
os.remove(path)
刪除路徑為path的文件。如果path 是一個文件夾,將拋出OSError; 查看下面的rmdir()刪除一個 directory。 |
| 46 |
os.removedirs(path)
遞歸刪除目錄。 |
| 47 |
os.rename(src, dst)
重命名文件或目錄,從 src 到 dst |
| 48 |
os.renames(old, new)
遞歸地對目錄進行更名,也可以對文件進行更名。 |
| 49 |
os.rmdir(path)
刪除path指定的空目錄,如果目錄非空,則拋出一個OSError異常。 |
| 50 |
os.stat(path)
獲取path指定的路徑的信息,功能等同於C API中的stat()系統調用。 |
| 51 |
os.stat_float_times([newvalue])
決定stat_result是否以float對象顯示時間戳
|
| 52 |
os.statvfs(path)
獲取指定路徑的文件系統統計信息 |
| 53 |
os.symlink(src, dst)
創建一個軟鏈接 |
| 54 |
os.tcgetpgrp(fd)
返回與終端fd(一個由os.open()返回的打開的文件描述符)關聯的進程組 |
| 55 |
os.tcsetpgrp(fd, pg)
設置與終端fd(一個由os.open()返回的打開的文件描述符)關聯的進程組為pg。 |
| 56 |
os.tempnam([dir[, prefix]])
返回唯一的路徑名用於創建臨時文件。 |
| 57 |
os.tmpfile()
返回一個打開的模式為(w+b)的文件對象 .這文件對象沒有文件夾入口,沒有文件描述符,將會自動刪除。 |
| 58 |
os.tmpnam()
為創建一個臨時文件返回一個唯一的路徑 |
| 59 |
os.ttyname(fd)
返回一個字元串,它表示與文件描述符fd 關聯的終端設備。如果fd 沒有與終端設備關聯,則引發一個異常。 |
| 60 |
os.unlink(path)
刪除文件路徑 |
| 61 |
os.utime(path, times)
返回指定的path文件的訪問和修改的時間。 |
| 62 |
os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])
輸出在文件夾中的文件名通過在樹中遊走,向上或者向下。 |
| 63 |
os.write(fd, str)
寫入字元串到文件描述符 fd中. 返回實際寫入的字元串長度 |
❸ Python os模塊
Python2.7.8(default,Jun302014,16:03:49)[MSCv.150032bit(Intel)]onwin32
Type"help","right","credits"or"license"formoreinformation.
>>>importos
>>>dir(os)
['F_OK','O_APPEND','O_BINARY','O_CREAT','O_EXCL','O_NOINHERIT','O_RANDOM',
'O_RDONLY','O_RDWR','O_SEQUENTIAL','O_SHORT_LIVED','O_TEMPORARY','O_TEXT',
'O_TRUNC','O_WRONLY','P_DETACH','P_NOWAIT','P_NOWAITO','P_OVERLAY','P_WAIT',
'R_OK','SEEK_CUR','SEEK_END','SEEK_SET','TMP_MAX','UserDict','W_OK','X_OK',
'_Environ','__all__','__builtins__','__doc__','__file__','__name__',
'__package__','__reg','_execvpe','_exists','_exit','_get_exports_list',
'_make_stat_result','_make_statvfs_result','_pickle_stat_result',
'_pickle_statvfs_result','abort','access','altsep','chdir','chmod','close',
'closerange','curdir','defpath','devnull','p','p2','environ','errno',
'error','execl','execle','execlp','execlpe','execv','execve','execvp',
'execvpe','extsep','fdopen','fstat','fsync','getcwd','getcw','getenv',
'getpid','isatty','kill','linesep','listdir','lseek','lstat','makedirs',
'mkdir','name','open','pardir','path','pathsep','pipe','popen','popen2',
'popen3','popen4','putenv','read','remove','removedirs','rename','renames',
'rmdir','sep','spawnl','spawnle','spawnv','spawnve','startfile','stat',
'stat_float_times','stat_result','statvfs_result','strerror','sys','system',
'tempnam','times','tmpfile','tmpnam','umask','unlink','unsetenv',
'urandom','utime','waitpid','walk','write']
>>>
首先,根據報錯信息,可以得到os沒有 getlogin()
然後,dir(os)看到確實沒有
使用dir可以查看當前模塊的所有屬性 及方法
❹ 使用python寫文件時,如何做到寫入文件由於外力刪掉了之後可以新創建一個同名文件並繼續寫入
你的試驗很詳細。不過這個現象在linux下可能與windows下不一樣。 通常改名或者是刪除後文件就失效了。寫入操作也是無效的。
為了防止別人修改你的文件,通常在寫入時,會加上一個鎖。使用操作系統特有的open方法才可以加鎖。
可以使用portalocker,filelock 也可以使用posixfile,
os.open能不能成呢?按理可以。不過C語言里使用fopen沒有這個功能,不過使用fcntl里的open可以。
你加了鎖後,別人就不能寫。文件處於佔用狀態。
另外操作系統都有一種文件監控機制的消息通知。具體忘記了。在unix與windows都有這個功能。當別人程序修改了某個文件,你會立刻得到消息通知。
補充一些教程。os.open還是可以用的。
os.open(file, flags[, mode]);
Parameters
file -- File name to be opened.
flags -- This is the following constants are options for the flags. They can be combined using the bitwise OR operator |. Some of them are not available on all platforms.
os.O_RDONLY: open for reading only
os.O_WRONLY: open for writing only
os.O_RDWR : open for reading and writing
os.O_NONBLOCK: do not block on open
os.O_APPEND: append on each write
os.O_CREAT: create file if it does not exist
os.O_TRUNC: truncate size to 0
os.O_EXCL: error if create and file exists
os.O_SHLOCK: atomically obtain a shared lock
os.O_EXLOCK: atomically obtain an exclusive lock
os.O_DIRECT: eliminate or rece cache effects
os.O_FSYNC : synchronous writes
os.O_NOFOLLOW: do not follow symlinks
mode -- This work in similar way as it works for chmod() method.
❺ C#數據寫成txt文本數據丟失問題。代碼如下。本機測試正常。XP系統。在伺服器會偶爾丟失幾條數據。03系統
難道是和我剛總結的,別人寫python時遇到的問題類似?
別人的那個問題,是需要保證關閉文件時,如何確保文件寫入的數據真正已生效了。
python中是
file.Flush()
然後調用
os.fsync()
去強制操作系統寫回的。
具體帖子標題為:
【整理】Python中寫完文件再關閉後,不知道需要sleep多長時間才是安全的(才能保持數據真正寫入了)
不知道你這里,是不是也要調用MS下相關的_commit()方面的函數,才可以避免數據丟失的。
註:
python的相關解釋:
os.fsync(fd)
Force write of file with filedescriptor fd to disk. On Unix, this calls the native fsync() function; on Windows, the MS _commit() function.
(此處不給貼地址,想要看帖子的全部內容的話,請自己google搜帖子標題,即可找到帖子地址)
❻ python如何查看一個模塊下所屬的函數如下圖所示
使用dir函數
>>> import os
>>> dir(os)
['F_OK', 'MutableMapping', 'O_APPEND', 'O_BINARY', 'O_CREAT', 'O_EXCL', 'O_NOINHERIT', 'O_RANDOM', 'O_RDONLY', 'O_RDWR', 'O_SEQUENTIAL', 'O_SHORT_LIVED', 'O_TEMPORARY', 'O_TEXT', 'O_TRUNC', 'O_WRONLY', 'P_DETACH', 'P_NOWAIT', 'P_NOWAITO', 'P_OVERLAY', 'P_WAIT', 'R_OK', 'SEEK_CUR', 'SEEK_END', 'SEEK_SET', 'TMP_MAX', 'W_OK', 'X_OK', '_Environ', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_execvpe', '_exists', '_exit', '_get_exports_list', '_putenv', '_unsetenv', '_wrap_close', 'abort', 'access', 'altsep', 'chdir', 'chmod', 'close', 'closerange', 'cpu_count', 'curdir', 'defpath', 'device_encoding', 'devnull', 'p', 'p2', 'environ', 'errno', 'error', 'execl', 'execle', 'execlp', 'execlpe', 'execv', 'execve', 'execvp', 'execvpe', 'extsep', 'fdopen', 'fsdecode', 'fsencode', 'fstat', 'fsync', 'ftruncate', 'get_exec_path', 'get_handle_inheritable', 'get_inheritable', 'get_terminal_size', 'getcwd', 'getcwdb', 'getenv', 'getlogin', 'getpid', 'getppid', 'isatty', 'kill', 'linesep', 'link', 'listdir', 'lseek', 'lstat', 'makedirs', 'mkdir', 'name', 'open', 'pardir', 'path', 'pathsep', 'pipe', 'popen', 'putenv', 'read', 'readlink', 'remove', 'removedirs', 'rename', 'renames', 'replace', 'rmdir', 'scandir', 'sep', 'set_handle_inheritable', 'set_inheritable', 'spawnl', 'spawnle', 'spawnv', 'spawnve', 'st', 'startfile', 'stat', 'stat_float_times', 'stat_result', 'statvfs_result', 'strerror', 'supports_bytes_environ', 'supports_dir_fd', 'supports_effective_ids', 'supports_fd', 'supports_follow_symlinks', 'symlink', 'sys', 'system', 'terminal_size', 'times', 'times_result', 'truncate', 'umask', 'uname_result', 'unlink', 'urandom', 'utime', 'waitpid', 'walk', 'write']
>>>
❼ python,如何在shell下查看一個模塊有哪些方法
如:
>>>importos
>>>dir(os)
['F_OK','O_APPEND','O_BINARY','O_CREAT','O_EXCL','O_NOINHERIT','O_RANDOM','O_RDONLY','O_RDWR','O_SEQUENTIAL','O_SHORT_LIVED','O_TEMPORARY','O_TEXT','O_TRUN
OWAIT','P_NOWAITO','P_OVERLAY','P_WAIT','R_OK','SEEK_CUR','SEEK_END','SEEK_SET','TMP_MAX','UserDict','W_OK','X_OK','_Environ','__all__','__builtins__','_
'__package__','__reg','_execvpe','_exists','_exit','_get_exports_list','_make_stat_result','_make_statvfs_result','_pickle_stat_result','_pickle_statvfs_r
ep','chdir','chmod','close','closerange','curdir','defpath','devnull','p','p2','environ','errno','error','execl','execle','execlp','execlpe','execv
,'extsep','fdopen','fstat','fsync','getcwd','getcw','getenv','getpid','isatty','kill','linesep','listdir','lseek','lstat','makedirs','mkdir','name',
ep','pipe','popen','popen2','popen3','popen4','putenv','read','remove','removedirs','rename','renames','rmdir','sep','spawnl','spawnle','spawnv','spawn
float_times','stat_result','statvfs_result','strerror','sys','system','tempnam','times','tmpfile','tmpnam','umask','unlink','unsetenv','urandom','utime',
>>>
❽ 如何安裝和使用Beanstalkd工作隊列
使用aptitude安裝:
下載並安裝Beanstalkd運行以下命令:
aptitude install -y beanstalkd
編輯默認配置文件讓隨著系統啟動
vim /etc/default/beanstalkd
打開文件後,向下滾動並找到底部線#開始= yes。將其更改為:
START=yes
下面介紹源碼安裝
我們需要從源代碼安裝過程的一個關鍵工具- Git。
運行以下獲取Git在你系統上:
aptitude install -y git
下載必要的開發工具軟體包:
aptitude install -y build-essential
使用Git克隆(下載)官方庫:
git clone https://github.com/kr/beanstalkd
進入到下載目錄:
cd beanstalkd
從源代碼構建應用程序:
make
安裝:
make install
再介紹一下centos下源碼安裝:
下載地址:
wget http://cloud.github.com/downloads/kr/beanstalkd/beanstalkd-1.4.6.tar.gz
解壓:
tar xzf beanstalkd-1.4.6.tar.gz
cd beanstalkd-1.4.6
/configure
make
make install
默認安裝路徑 :/usr/local/bin/
查看版本:
/usr/local/bin/beanstalkd -v
1.4.6
再附加一個啟動腳本,從Fedora下挖來的 startup 腳本:
#!/bin/sh
#
# beanstalkd - a simple, fast workqueue service
#
# chkconfig: - 57 47
# description: a simple, fast workqueue service
# processname: beanstalkd
# config: /etc/sysconfig/beanstalkd
#
### BEGIN INIT INFO
# Provides: beanstalkd
# Required-Start: $local_fs $network $remote_fs
# Required-Stop: $local_fs $network $remote_fs
# Default-Stop: 0 1 2 6
# Short-Description: start and stop beanstalkd
# Description: a simple, fast work-queue service
### END INIT INFO
# Source function library.
/etc/rc.d/init.d/functions
# Source networking configuration.
/etc/sysconfig/network
# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit
exec="/usr/local/bin/beanstalkd"
prog=$(basename $exec)
# default options, overruled by items in sysconfig
BEANSTALKD_ADDR=127.0.0.1
BEANSTALKD_PORT=11300
BEANSTALKD_USER=beanstalkd
[ -e /etc/sysconfig/beanstalkd ] && . /etc/sysconfig/beanstalkd
lockfile=/var/lock/subsys/beanstalkd
start() {
[ -x $exec ] || exit 5
echo -n $"Starting $prog: "
# if not running, start it up here, usually something like "daemon $exec"
options="-l ${BEANSTALKD_ADDR} -p ${BEANSTALKD_PORT} -u ${BEANSTALKD_USER}"
if [ "${BEANSTALKD_MAX_JOB_SIZE}" != "" ]; then
options="${options} -z ${BEANSTALKD_MAX_JOB_SIZE}"
fi
if [ "${BEANSTALKD_BINLOG_DIR}" != "" ]; then
if [ ! -d "${BEANSTALKD_BINLOG_DIR}" ]; then
echo "Creating binlog directory (${BEANSTALKD_BINLOG_DIR})"
mkdir -p ${BEANSTALKD_BINLOG_DIR} && chown ${BEANSTALKD_USER}:${BEANSTALKD_USER} ${BEANSTALKD_BINLOG_DIR}
fi
options="${options} -b ${BEANSTALKD_BINLOG_DIR}"
if [ "${BEANSTALKD_BINLOG_FSYNC_PERIOD}" != "" ]; then
options="${options} -f ${BEANSTALKD_BINLOG_FSYNC_PERIOD}"
else
options="${options} -F"
fi
if [ "${BEANSTALKD_BINLOG_SIZE}" != "" ]; then
options="${options} -s ${BEANSTALKD_BINLOG_SIZE}"
fi
fi
daemon $exec -d $options
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
return $retval
}
stop() {
echo -n $"Stopping $prog: "
# stop it here, often "killproc $prog"
killproc $prog -INT
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}
restart() {
stop
start
}
reload() {
restart
}
force_reload() {
restart
}
rh_status() {
# run checks to determine if the service is running or use generic status
status $prog
}
rh_status_q() {
rh_status >/dev/null 2>&1
}
case "$1" in
start)
rh_status_q && exit 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
force-reload)
force_reload
;;
status)
rh_status
;;
condrestart|try-restart)
rh_status_q || exit 0
restart
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
exit 2
esac
exit $?
使用Beanstalkd
在安裝之後,您就可以開始使用Beanstalkd伺服器。以下是運行守護進程的選項:
-b DIR wal directory
-f MS fsync at most once every MS milliseconds (use -f0 for "always fsync")
-F never fsync (default)
-l ADDR listen on address (default is 0.0.0.0)
-p PORT listen on port (default is 11300)
-u USER become user and group
-z BYTES set the maximum job size in bytes (default is 65535)
-s BYTES set the size of each wal file (default is 10485760)
(will be rounded up to a multiple of 512 bytes)
-c compact the binlog (default)
-n do not compact the binlog
-v show version information
-V increase verbosity
-h show this help
使用例子:
# Usage: beanstalkd -l [ip address] -p [port #]
# For local only access:
beanstalkd -l 127.0.0.1 -p 11301 &
管理服務:
如果安裝包管理器(i.e. aptitude),你將能夠管理Beanstalkd作為服務守護進程。
# To start the service:
service beanstalkd start
# To stop the service:
service beanstalkd stop
# To restart the service:
service beanstalkd restart
# To check the status:
service beanstalkd status
獲得Beanstalkd客戶端庫
Beanstalkd配有一長串的支持客戶端庫來處理許多不同的應用程序部署。這個列表的支持語言和框架,包括:
●Python
●Django
●Go
●Java
●Node.js
●Perl
●PHP
●Ruby
●and more.
查看完整列表支持,尋找你最喜歡的語言和安裝說明,查看客戶端庫頁面Beanstalkd Github上。
使用Beanstalkd
在本節之前,完成這篇文章,讓我們快速Beanstalkd的基本用法。在我們的示例中,我們將使用Python語言和Beanstald Python bindings ——beanstalkc。
安裝beanstalkc,運行以下命令:
pip install pyyaml
pip install beanstalkc
基本操作
在所有Python文件你想處理Beanstalkd時,需要導入beanstalkc並連接:
import beanstalkc
# Connection
beanstalk = beanstalkc.Connection(host='localhost', port=11301)
To enqueue a job:
beanstalk.put('job_one')
To receive a job:
job = beanstalk.reserve()
# job.body == 'job_one'
To delete a job after processing it:
job.delete()
To use a specific tube (i.e. queue / list):
beanstalk.use('tube_a')
To list all available tubes:
beanstalk.tubes()
# ['default', 'tube_a']
Final example (nano btc_ex.py):
import beanstalkc
# Connect
beanstalk = beanstalkc.Connection(host='localhost', port=11301)
# See all tubes:
beanstalk.tubes()
# Switch to the default (tube):
beanstalk.use('default')
# To enqueue a job:
beanstalk.put('job_one')
# To receive a job:
job = beanstalk.reserve()
# Work with the job:
print job.body
# Delete the job:
job.delete()
當您運行上面的腳本時,您應該會看到工作的主體被列印:
python btc_ex.py
# job_one