Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于在Python中下载NCBI文件的多线程_Python_Multithreading_Urllib2 - Fatal编程技术网

用于在Python中下载NCBI文件的多线程

用于在Python中下载NCBI文件的多线程,python,multithreading,urllib2,Python,Multithreading,Urllib2,因此,最近我承担了从ncbi数据库下载大量文件的任务。但是,我遇到过必须创建多个数据库的情况。此代码用于从ncbi网站下载所有病毒。我的问题是,有没有办法加快下载这些文件的速度 目前该程序的运行时间超过5小时。我曾经研究过多线程,但一直无法让它工作,因为其中一些文件需要10秒以上才能下载,我不知道如何处理延迟。(编程新手)还有一种方法可以处理urllib2.HTTPError:HTTP Error 502:Bad Gateway。我有时会通过retstart和retmax的某些组合得到这种效果。

因此,最近我承担了从ncbi数据库下载大量文件的任务。但是,我遇到过必须创建多个数据库的情况。此代码用于从ncbi网站下载所有病毒。我的问题是,有没有办法加快下载这些文件的速度

目前该程序的运行时间超过5小时。我曾经研究过多线程,但一直无法让它工作,因为其中一些文件需要10秒以上才能下载,我不知道如何处理延迟。(编程新手)还有一种方法可以处理urllib2.HTTPError:HTTP Error 502:Bad Gateway。我有时会通过retstart和retmax的某些组合得到这种效果。这会使程序崩溃,我必须通过更改for语句中的0从其他位置重新启动下载

import urllib2
from BeautifulSoup import BeautifulSoup

#This is the SearchQuery into NCBI. Spaces are replaced with +'s.
SearchQuery = 'viruses[orgn]+NOT+Retroviridae[orgn]'
#This is the Database that you are searching.
database = 'protein'
#This is the output file for the data
output = 'sample.fasta'


#This is the base url for NCBI eutils.
base = 'http://eutils.ncbi.nlm.nih.gov/entrez/eutils/'
#Create the search string from the information above
esearch = 'esearch.fcgi?db='+database+'&term='+SearchQuery+'&usehistory=y'
#Create your esearch url
url = base + esearch
#Fetch your esearch using urllib2
print url
content = urllib2.urlopen(url)
#Open url in BeautifulSoup
doc = BeautifulSoup(content)
#Grab the amount of hits in the search
Count = int(doc.find('count').string)
#Grab the WebEnv or the history of this search from usehistory.
WebEnv = doc.find('webenv').string
#Grab the QueryKey
QueryKey = doc.find('querykey').string
#Set the max amount of files to fetch at a time. Default is 500 files.
retmax = 10000
#Create the fetch string
efetch = 'efetch.fcgi?db='+database+'&WebEnv='+WebEnv+'&query_key='+QueryKey
#Select the output format and file format of the files. 
#For table visit: http://www.ncbi.nlm.nih.gov/books/NBK25499/table/chapter4.chapter4_table1
format = 'fasta'
type = 'text'
#Create the options string for efetch
options = '&rettype='+format+'&retmode='+type


#For statement 0 to Count counting by retmax. Use xrange over range
for i in xrange(0,Count,retmax):
    #Create the position string
    poision = '&retstart='+str(i)+'&retmax='+str(retmax)
    #Create the efetch URL
    url = base + efetch + poision + options
    print url
    #Grab the results
    response = urllib2.urlopen(url)
    #Write output to file
    with open(output, 'a') as file:
        for line in response.readlines():
            file.write(line)
    #Gives a sense of where you are
    print Count - i - retmax

您应该使用多线程,这是下载任务的正确方式

"these files take more than 10seconds to download and I do not know how to handle stalling",
我不认为这是一个问题,因为Python的多线程将处理这个问题,或者我更愿意说多线程只是用于这种I/O绑定的工作。当一个线程等待下载完成时,CPU会让其他线程完成他们的工作


无论如何,你最好至少试着看看会发生什么。

两种方法可以影响你的任务。1.使用进程而不是线程,多进程是您应该使用的模块。2.使用基于事件的方法,gevent是正确的模块

502错误不是脚本的错误。简单地说,可以使用以下模式进行重试

try_count = 3
while try_count > 0:
    try:
        download_task()
    except urllib2.HTTPError:
        clean_environment_for_retry()
    try_count -= 1

在except行中,您可以根据具体的HTTP状态代码细化细节以执行特定操作。

要使用多线程下载文件:

#!/usr/bin/env python
import shutil
from contextlib import closing
from multiprocessing.dummy import Pool # use threads
from urllib2 import urlopen

def generate_urls(some, params): #XXX pass whatever parameters you need
    for restart in range(*params):
        # ... generate url, filename
        yield url, filename

def download((url, filename)):
    try:
        with closing(urlopen(url)) as response, open(filename, 'wb') as file:
            shutil.copyfileobj(response, file)
    except Exception as e:
        return (url, filename), repr(e)
    else: # success
        return (url, filename), None

def main():
    pool = Pool(20) # at most 20 concurrent downloads
    urls = generate_urls(some, params)
    for (url, filename), error in pool.imap_unordered(download, urls):
        if error is not None:
           print("Can't download {url} to {filename}, "
                 "reason: {error}".format(**locals())

if __name__ == "__main__":
   main()

对此建议的一个警告是,如果文件集合确实很大,并且您尝试使用一个线程来下载每个文件,那么python解释器可能会崩溃。我在OSX中做了类似的事情,当我的下载程序达到大约120个线程时,解释器崩溃了。谢谢。我将研究在代码中加入更多try,catch语句。我更多的是在寻找一种方法来实现多重目标-threading@DarthBunny:
HTTPError
具有
code
属性,例如404(未找到)、400(错误请求)。如果您认为某些错误是暂时的,那么在
中收集这些URL,如果错误不是None
块并重复循环(次数有限)。我使用了
repr(e)
作为一个最不可能中断的函数。如果使用线程而不是进程,则可以只返回
e
,如果error不是None,则可以在
中访问
e.code
block@DarthBunny:要检查下载是否正确,您可以检查
response
标题,例如:。,
内容长度
以字节为单位找出大小,并将其与下载的文件进行比较。部分下载可能是由于复制过程中出现异常,您可以删除
os.remove(filename)
中的
Exception
块。如果所有结果都来自同一个站点,请阅读其TOS。