發表文章

目前顯示的是有「Python」標籤的文章

以樂透為例,用Python統計馬可夫矩陣

圖片
答案是矩陣裡的每個元素都是 1/49 (下一期開出某個號碼的機率),完畢。 寫這篇的目的並不是真的想要得到"明牌",只是找個題目練習一下 Python 與馬可夫模型;另一方面,樂透是大家都感興趣的題目,希望這樣應該比較容易理解,並不是真的可以算出明牌,如果有執迷不悟的,本文最後會說明為什麼。 馬可夫鏈 是機率問題中很常使用的模型,近年來因為大數據盛行,每個領域需要網路爬蟲收集大量資料 (分析關鍵字), 自然語言處理 (NLP) 於是成為很熱門的領域,而 Markov model 是 使用統計方法處理自然語言時常用的方法,google 也是 使用 Markov model 來為每個網頁做 ranking。基本原理是,把每個網站當作節點,然後把連入與連出的連結當作是每個節點的連線,那抵達某個特定節點的機率就代表該頁面 (page) 的知名度;越容易抵達某個網頁代表被很多網頁參考,也就是該網頁知名度越高。 簡單來說,馬可夫模型主要就是從這個狀態到下一個狀態給定機率 P,而目前狀態到所有下一個狀態的機率總和一定為1。馬可夫矩陣可以用下圖表示: 上圖用大樂透來說明的話,本文要來練習的題目,目標是 統計出 106 年度每個號碼跟下期號碼之間的機率 ,i, j 都是 49,例如: P 25,49 代表本期開 25 號而下一期開 49 號的機率,而 P 25,1 P 25,2 ... P 25,49 加總起來會是 1。 再說一次,機率理論值其實都是 1/49,這邊只是練習馬可夫模型與 Python ,因為樣本數太小,人很容易會覺得每期的號碼之間有關連,但是純粹只是機率問題。當統計的期數越多,其實會發現機率會越接近 1/49,本文只是幫助理解/說明與練習。 首先從網路上找到 106 年開獎的資料,內容如下,把內容存成 csv 檔案。Index 代表每一期開獎的號碼,Drop是落球順序,Seq是排序後的開獎順序,Special是特別號。 Index,Month,Day,Weekday,Drop1,Drop2,Drop3,Drop4,Drop5,Drop6,Seq1,Seq2,Seq3,Seq4,Seq5,Seq6,Special 1,1,3,二,18,41,47,49,22,42,18,22,41,42,47,49,45...

Python datetime 相關的使用方法

這會是一篇持續更新的文章,會把 datetime 相關的學習記錄下來。 from datetime import datetime, date, timedelta date.today() datetime.today() datetime.now().strftime("%Y-%m-%d %H:%M:%S") datetime.now().date() datetime.today() - timedelta(days=1) datetime.combine(date.today(), datetime.strptime(str_some_time, '%H:%M').time()) if (abs(datetime.today() - some_time) <= timedelta(minutes=10)):     print ("less than 10 minutes")

將 Jenkins Job 的歷史結果整理出視覺化的 Daily Report mail (二)

圖片
前一篇文章 說明了 Daily Report 的 Jenkins Job 設定,接下來本篇會說明如何實作 daily_report.py 這個 script 會生成像這樣的 PNG 圖表: 首先要安裝 Pandas 及 matplotlib ,我們會使用 Pandas 來讀取 csv 檔案並使用相關便捷的功能來簡化/加速資料分析的步驟,並使用 matplotlib 來產生視覺化的 PNG 圖檔。 python -m pip install Pandas python -m pip install matplotlib script 相關的 module import 如下: 1 2 3 4 5 6 import os , time , sys , re import numpy as np import pandas as pd import matplotlib.pyplot as plt import matplotlib.dates as mdates from datetime import datetime, date, timedelta 我們在 Jenkins Job 內設定預設讀取 config\daily_report_demo.prop,當作 Job 參數。 config\daily_report_demo.prop 的內容如下: MY_JOB_NAME=daily_report_demo DAILY_REPORT_MAIL_TO=my_account@gmail.com MY_JOB_NAME 是指定上游 Jenkins Job 的 Job name,意思就是這個 Daily Report 是統整 daily_report_demo 這個 Job 的建置結果。所以接下來: 讀取 WORKSPACE 環境變數,這個環境變數是 Jenkins 設定的,用來取得 Jenkins job 的自訂工作區位置,以我們之前的設定為例,工作區是在 D:\workshop 讀取 MY_JOB_NAME 環境變數 1 2 3 4 5 6 7 8 9 10 11 12 13 if __name__ == '__ma...

將 Jenkins Job 的歷史結果整理出視覺化的 Daily Report mail (一)

圖片
當初在處理這個問題的時候,大部分都是參考國外的網站,使用 Jenkins 內建功能送 email 的文章很多,但是 像是要自訂 mail 內容,蒐集統整不同 Job 的狀態以及包含視覺化報表 的部分倒是很少看到,所以就做個紀錄與分享,一方面也是拋轉引玉,歡迎交流。 這裡的做法受限於 "Free-Style" 形式的 Jenkins Job,所以過程會比較繁瑣;但是換句話說,如果只想用 "Free-Style" 形式來創建 Jenkins Job,可以從這篇文章得到一些靈感。 這個主題為了盡量寫得詳細點,會分成三個部分: Jenkins Daily Report Job 的相關設定。( 本篇 ) 使用 Python/Pandas/matplotlib 做資料分析及處理 。 說明使用 jelly script 來客製化郵件內容 。 最後目標是每天自動送出視覺化統計 Jenkins Job 歷史狀態的 email,如下圖。 首先,本篇會說明以下主題: 設定 Jenkins 郵件相關 (gmail) SMTP 設定 需要安裝的 Jenkins Plugin 新增/設定一個 Jenkins "Daily Report" Job 這個系列 沒有 說明的部分如下: (我想這些在網路上應該都很容易可以找到相關資料) 安裝 Jenkins 設定 slave node,並在 slave node 上執行 Jenkins Job 設定 Jenkins 郵件相關 SMTP 設定 讓 Jenkins 寄出郵件需要設定 SMTP server,這邊以使用 gmail SMTP為範例。 Jenkins mail 設定在 "管理 Jenkins" => "設定系統"   http://localhost:8080/configure 詳細設定如下圖,設定完成可以勾選"寄測試信",先試試看設定是否正確。 如果看到 "電子郵件成功寄出"就代表設定正確了。 已知目前 google 認為 Jenkins Plugin登入SMTP的方式安全性較低,使用者必須要自行 "啟用安全性較低的應...

從 Python script 停止 Jenkins Job

之前分享過如何 使用 Jenkins API 取得 Job result ,這次來記錄一下如何 停止 執行中的 Job。 這次直接使用 requests ,如果沒有安裝可以先執行 pip install requests 安裝。 這個是比較簡潔的寫法,其實也可以直接用  python-jenkins 這類的 python wrapper 來控制 Jenkins server,通常如果有很多 jenkins server 控制的行為,就建議直接使用 python-jenkins 了。 以下是使用 requests 的範例: 1 2 3 4 5 6 7 8 9 10 11 import requests jenkinsMaster = "http://jenkinshost:8080" userID = "myaccount" APIToken = "1234567890" def stopJenkinsJob(job_name): url = jenkinsMaster + "/job/" + jobName + "/lastBuild/stop" auth = (userID, APIToken) r = requests . post(url, auth = auth) return r . status_code

常用的 Human Sorting with Python

簡單來說,當 sorting 的結果跟預期的不同,可以試一下。其中奧妙就不多說了,附上原始網址,可以研究一下。 https://stackoverflow.com/questions/5967500/how-to-correctly-sort-a-string-with-a-number-inside 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import re , os def atoi(text): return int (text) if text . isdigit() else text def natural_keys(text): ''' alist.sort(key=natural_keys) sorts in human order http://nedbatchelder.com/blog/200712/human_sorting.html (See Toothy's implementation in the comments) ''' return [ atoi(c) for c in re . split( '(\d+)' , text) ] try : dirs = os . listdir(folder) dirs . sort(key = natural_keys) # just in case we need the reverse order #dirs = reversed(dirs) for file in dirs: if not file . endswith( "csv" ): continue csv_path = "%s\\%s" % (folder, file ) print (csv_path) except Exc...

在 Jenkins 環境下使用 adb

因為 Jenkins 在結束工作的時候,會將所有 fork 出來的子進程全部砍掉,來確保不會有 leakage 的情況發生,讓 Jenkins 可以長時間運行。通常這個行為是沒有問題的,有時候也可以仰賴這個行為來讓 Job Script 寫起來簡潔一些,省一些功夫。 但是如果某個 Jenkins Job 會啟動 server or daemon 性質的 process,而我們希望當 Job 結束後, daemon process 可以保留,這個時候需要在一開始啟動這個 daemon 的時候,加上 "dontKillMe" 的環境變數,來告知 Jenkins 不要回收這個 process。 詳細說明可以參考 這裡 adb 就是一個很好的例子。 adb daemon 可以同時間處理很多 connection,通常在大規模的自動化測試中,一台 PC 會接著很多 device,如果 adb daemon 被砍掉,其他 device connection 就會中斷,這並不是我們希望看到的。 以下是針對指定 adb server 不要被 Jenkins 回收的範例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 jenkins_env = os . environ . copy() jenkins_env[ "BUILD_ID" ] = "dontKillMe" start_time = time . clock() event = Event() is_device_timeout = False cmd = "adb -s %s wait-for-device" % (deviceNo) try : adb_pid = subprocess . Popen(cmd, env = jenkins_env) while adb_pid . poll() is None : event . wait(timeout = 1.0 ) if (time . clock() -...