Python多線程使用Queue和Thread來加速用Ensembl REST API查找variant資訊

現在主要生物醫學資料庫如ensembl, nubi都有開放API接口,可以直接用程式去提出一堆的請求,不用像傳統的網頁查找那樣,省掉很多麻煩,只要稍微瞭解一下http原理,各種程式語言如R的httr中文教學)或 是Python的requests,使用起來都算方便,

這裡遇到一個小問題,應該說想要更好的解決它:如何加速查找速度,假如我有上千個想要查找的資料?
舉例來說,當你想要找一大串4000個基因變異、相關基因功能,雖然不需要在網頁上點選4000次(可能花好幾天吧),幾行程式碼就可以解決,但當要丟4000次請求,來取得資料時,假設1次請求,要花5秒種取得資料,那麼4000次,還是要花6個小時,那要怎麼改善這個問題呢?因為我們很貪心的想要花更少時間(假如網路頻寬很大的話)

一種最直覺的方式,便是把要查找的variant列表,切成多份,然後同時跑,最後再把資料整合起來。

另外,因抱持者想要探索看看新方法,便嘗試使用Python中的QueueThread,用多線程的方式來解決這個問題。

我基本思路是將我要查找的Rsid(Variant的資訊),用iterator的方式來吐出每次要query的id,而Queue object可以把我處理好跟我所開啟thread間資訊同步的問題。

這邊是最後使用的代碼

#這邊是我想要查找的基因變異variant的ID
test = RSID.iteritems()

#我希望開的線程數量
concurrent = 10

#因為資料是以json檔傳回,最後我都要塞回這個test_list中
test_list = {}

#使用queue的重點,是要解決共享變數不能被thread同時讀取的問題,他可以有效解決thread間在取用共享變數的問題
que = queue.Queue()
for i in range(concurrent):
    que.put(next(test)[1])

def doWork(*args):
    tmp = args[0]
    while tmp.qsize() > 0:
        rsid = tmp.get()
        test_list[rsid]=rsid
        #這邊是ensembl Rest API的接口
        server = "http://grch37.rest.ensembl.org"
        url_1 = "/variation/human/"
        url_2 = "?pops=1"
        ext = url_1+rsid+url_2
        r = requests.get(server+ext, headers={ "Content-Type" : "application/json"})

        if not r.ok:
            r.raise_for_status()
            sys.exit()
        decoded = r.json()
        test_list[rsid] = decoded

print("\t[Info] Queue size={0}".format(que.qsize()))

# 這邊是線程開啟和運行的地方
for i in range(concurrent):
    thread_name='Thd'+i
    t = threading.Thread(target=doWork, name=thread_name, args=(que,))
    t.daemon = True
    t.start() 

td = datetime.datetime.now() - st
print("\t[Info] Spending time={0}!".format(td))

P.S:後記,這種方式其實頗危險的,假如所使用的服務管理者,會特別管理高頻要資源的IP那麼就要注意,可能從此ip就被封了,所以最好可以掛載proxy在進行query,另一方面,時間允許下,就用單線慢慢抓吧!甚至必須去測試對方有沒有限制每秒能query的數量,就要去調適最佳化的參數!

閱讀參考:

Python Queue 模塊
what is the fastest way to send 100,000 HTTP requests in Python?
using iterators and generators in multi-threaded applications
iterables/iterators/generators
How many threads is too many?
Python模塊學習 – threading 多線程控制和處理

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s