2013-02-12 65 views
1

我有一個帶有GI號碼的文件,想從ncbi獲得FASTA序列。urllib2.HTTPError Python

from Bio import Entrez 
import time 
Entrez.email ="[email protected]" 
f = open("C:\\bioinformatics\\gilist.txt") 
for line in iter(f): 
    handle = Entrez.efetch(db="nucleotide", id=line, retmode="xml") 
    records = Entrez.read(handle) 
    print ">GI "+line.rstrip()+" "+records[0]["GBSeq_primary-accession"]+" "+records[0]["GBSeq_definition"]+"\n"+records[0]["GBSeq_sequence"] 
    time.sleep(1) # to make sure not many requests go per second to ncbi 
f.close() 

這個腳本運行良好,但在幾個序列後突然出現這個錯誤信息。

Traceback (most recent call last): 
    File "C:/Users/Ankur/PycharmProjects/ncbiseq/getncbiSeq.py", line 7, in <module> 
    handle = Entrez.efetch(db="nucleotide", id=line, retmode="xml") 
    File "C:\Python27\lib\site-packages\Bio\Entrez\__init__.py", line 139, in efetch 
    return _open(cgi, variables) 
    File "C:\Python27\lib\site-packages\Bio\Entrez\__init__.py", line 455, in _open 
    raise exception 
urllib2.HTTPError: HTTP Error 500: Internal Server Error 

我當然可以用http://www.ncbi.nlm.nih.gov/sites/batchentrez但我想創建一個管道,並會喜歡的東西自動化。

如何防止NCBI從「踢我出去」

回答

0

我不熟悉的NCBI API,但我的猜測是,你違反了某種速率限制規則(甚至用「睡眠( 1)「),因此您之前的請求可以正常工作,但是經過一些請求後,服務器會發現您經常觸碰並阻止您。這對你來說是有問題的,因爲你的代碼中沒有錯誤處理。

我建議在try/except塊中包裝數據獲取,以使您的腳本等待更長時間,然後在遇到問題時再試一次。如果一切都失敗了,把導致錯誤的id寫到一個文件並繼續(如果id是某種方式的罪魁禍首,可能導致Entrez庫產生一個錯誤的URL)。

試着改變你的代碼是這樣的(未經測試):

from urllib2 import HTTPError 
from Bio import Entrez 
import time 

def get_record(_id): 
    handle = Entrez.efetch(db="nucleotide", id=_id, retmode="xml") 
    records = Entrez.read(handle) 
    print ">GI "+line.rstrip()+" "+records[0]["GBSeq_primary-accession"]+" "+records[0]["GBSeq_definition"]+"\n"+records[0]["GBSeq_sequence"] 
    time.sleep(1) # to make sure not many requests go per second to ncbi 

Entrez.email ="[email protected]" 
f = open("C:\\bioinformatics\\gilist.txt") 
for id in iter(f): 
    try: 
     get_record(id) 
    except HTTPError: 
     print "Error fetching", id 
     time.sleep(5) # we have angered the API! Try waiting longer? 
     try: 
      get_record(id) 
     except: 
      with open('error_records.bad','a') as f: 
       f.write(str(id)+'\n') 
      continue # 
f.close() 
0

有一個叫周圍的工作efetch。你可以將你的列表分成200個批次(直覺,這是一個好的批量大小),並使用efetch一次發送所有這些ID。

首先,這比發送200個單獨的查詢要快得多。其次,它也有效地符合「每秒3查詢」規則,因爲每個查詢的處理時間長於0.33秒但不會太長。

但是,您確實需要一種機制來抓住「壞蘋果」。即使您的200個ID中有一個不好,NCBI也會返回0結果。換句話說,當且僅當所有200個ID都有效時,NCBI纔會返回結果。

在蘋果不好的情況下,我一個接一個地遍歷200個ID,忽略壞蘋果。這個「如果壞蘋果」的情況也會告訴你不要讓批量太大,以防蘋果不好。如果它很大,首先,有一個壞蘋果的機會更大,也就是說,你經常需要迭代整個事情。其次,批次越大,您必須迭代的個別項目越多。

我用下面的代碼來下載CAZY蛋白質和它工作得很好:

import urllib2 


prefix = "http://www.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=protein&rettype=fasta&id=" 
id_per_request = 200 


def getSeq (id_list): 
    url = prefix + id_list[:len(id_list)-1] 

    temp_content = "" 
    try: 
     temp_content += urllib2.urlopen(url).read() 

### if there is a bad apple, try one by one 
    except: 
     for id in id_list[:len(id_list)-1].split(","): 
      url = prefix + id 
    #print url 
      try: 
       temp_content += urllib2.urlopen(url).read() 
      except: 
      #print id 
       pass 
    return temp_content 


content = "" 
counter = 0 
id_list = "" 

#define your accession numbers first, here it is just an example!! 

accs = ["ADL19140.1","ABW01768.1","CCQ33656.1"] 
for acc in accs: 

    id_list += acc + "," 
    counter += 1 

    if counter == id_per_request: 
     counter = 0 
     content += getSeq(id_list) 
     id_list = "" 

if id_list != "": 
    content += getSeq(id_list) 
    id_list = "" 


print content