Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/337.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有限多线程_Python_Multithreading - Fatal编程技术网

Python有限多线程

Python有限多线程,python,multithreading,Python,Multithreading,你肯定知道,我可以用多线程从互联网上更快地下载文件。 但如果我向同一个网站发送大量请求,我可能会被列入黑名单 那么你能帮我实现类似的东西吗 我有一个URL列表。 我希望您下载所有这些文件,但如果已经有10个下载正在运行,请等待一个插槽 我将感谢任何帮助。 蒂克 比诺瓦 这就是我正在使用的代码不起作用 class PDBDownloader(threading.Thread): prefix = 'http://www.rcsb.org/pdb/files/' def __in

你肯定知道,我可以用多线程从互联网上更快地下载文件。 但如果我向同一个网站发送大量请求,我可能会被列入黑名单

那么你能帮我实现类似的东西吗 我有一个URL列表。 我希望您下载所有这些文件,但如果已经有10个下载正在运行,请等待一个插槽

我将感谢任何帮助。 蒂克

比诺瓦

这就是我正在使用的代码不起作用

class PDBDownloader(threading.Thread):

    prefix = 'http://www.rcsb.org/pdb/files/'

    def __init__(self, queue):
        threading.Thread.__init__(self)
        self.queue = queue
        self.pdbid = None
        self.urlstr = ''
        self.content = ''

    def run(self):
        while True:
            self.pdbid = self.queue.get()
            self.urlstr = self.prefix + pdbid + '.pdb'
            print 'downloading', pdbid
            self.download()

            filename = '%s.pdb' %(pdbid)
            f = open(filename, 'wt')
            f.write(self.content)
            f.close()

            self.queue.task_done()

    def download(self):
        try:
            f = urllib2.urlopen(self.urlstr)
        except urllib2.HTTPError, e:
            msg = 'HTTPError while downloading file %s at %s. '\
                    'Details: %s.' %(self.pdbid, self.urlstr, str(e))
            raise OstDownloadException, msg
        except urllib2.URLError, e:
            msg = 'URLError while downloading file %s at %s. '\
                    'RCSB erveur unavailable.' %(self.pdbid, self.urlstr)
            raise OstDownloadException, msg
        except Exception, e:
            raise OstDownloadException, str(e)
        else:
            self.content = f.read()
if __name__ == '__main__':

    pdblist = ['1BTA', '3EAM', '1EGJ', '2BV9', '2X6A']

    for i in xrange(len(pdblist)):
        pdb = PDBDownloader(queue)
        pdb.setDaemon(True)
        pdb.start()

    while pdblist:
        pdbid = pdblist.pop()
        queue.put(pdbid)

    queue.join()

使用具有URL共享列表的线程池。每个线程都试图从列表中弹出一个url并下载它,直到一个url都没有了。从列表中弹出是线程安全的

while True:
    try:
        url = url_list.pop()
        # download URL here
    except IndexError:
        break

使用具有URL共享列表的线程池。每个线程都试图从列表中弹出一个url并下载它,直到一个url都没有了。从列表中弹出是线程安全的

while True:
    try:
        url = url_list.pop()
        # download URL here
    except IndexError:
        break
使用线程不会更快地从Internet下载文件。你只有一张网卡和一个互联网连接,所以这不是真的

线程被用来等待,你不能再等得更快了

您可以使用一个线程,并且速度一样快,甚至更快—只是不要在启动另一个文件之前等待一个文件的响应。换句话说,使用异步、无阻塞的网络编程

下面是一个完整的脚本,它使用twisted.internet.task.coiterate同时启动多个下载,而不使用任何线程,并且考虑到池大小,我在演示中使用了两个同时下载,但您可以更改大小:

from twisted.internet import defer, task, reactor
from twisted.web import client
from twisted.python import log

@defer.inlineCallbacks
def deferMap(job, dataSource, size=1):
    successes = []
    failures = []

    def _cbGather(result, dataUnit, succeeded):
        """This will be called when any download finishes"""
        if succeeded:
            # you could save the file to disk here
            successes.append((dataUnit, result))
        else:
            failures.append((dataUnit, result))

    @apply
    def work():
        for dataUnit in dataSource:
            d = job(dataUnit).addCallbacks(_cbGather, _cbGather,
                callbackArgs=(dataUnit, True),  errbackArgs=(dataUnit, False))
            yield d

    yield defer.DeferredList([task.coiterate(work) for i in xrange(size)])
    defer.returnValue((successes, failures))

def printResults(result):
    successes, failures = result
    print "*** Got %d pages total:" % (len(successes),)
    for url, page in successes:
        print '  * %s -> %d bytes' % (url, len(page))
    if failures:
        print "*** %d pages failed download:" % (len(failures),)
        for url, failure in failures:
            print '  * %s -> %s' % (url, failure.getErrorMessage())

if __name__ == '__main__':
    import sys
    log.startLogging(sys.stdout)
    urls = ['http://twistedmatrix.com',
            'XXX',
            'http://debian.org',
            'http://python.org',
            'http://python.org/foo',
            'https://launchpad.net',
            'noway.com',
            'somedata',
        ]
    pool = deferMap(client.getPage, urls, size=2) # download 2 at once
    pool.addCallback(printResults)
    pool.addErrback(log.err).addCallback(lambda ign: reactor.stop())
    reactor.run()
请注意,我故意包含了一些错误的URL,因此我们可以在结果中看到一些失败:

...
2010-06-29 08:18:04-0300 [-] *** Got 4 pages total:
2010-06-29 08:18:04-0300 [-]   * http://twistedmatrix.com -> 16992 bytes
2010-06-29 08:18:04-0300 [-]   * http://python.org -> 17207 bytes
2010-06-29 08:18:04-0300 [-]   * http://debian.org -> 13820 bytes
2010-06-29 08:18:04-0300 [-]   * https://launchpad.net -> 18511 bytes
2010-06-29 08:18:04-0300 [-] *** 4 pages failed download:
2010-06-29 08:18:04-0300 [-]   * XXX -> Connection was refused by other side: 111: Connection refused.
2010-06-29 08:18:04-0300 [-]   * http://python.org/foo -> 404 Not Found
2010-06-29 08:18:04-0300 [-]   * noway.com -> Connection was refused by other side: 111: Connection refused.
2010-06-29 08:18:04-0300 [-]   * somedata -> Connection was refused by other side: 111: Connection refused.
...
使用线程不会更快地从Internet下载文件。你只有一张网卡和一个互联网连接,所以这不是真的

线程被用来等待,你不能再等得更快了

您可以使用一个线程,并且速度一样快,甚至更快—只是不要在启动另一个文件之前等待一个文件的响应。换句话说,使用异步、无阻塞的网络编程

下面是一个完整的脚本,它使用twisted.internet.task.coiterate同时启动多个下载,而不使用任何线程,并且考虑到池大小,我在演示中使用了两个同时下载,但您可以更改大小:

from twisted.internet import defer, task, reactor
from twisted.web import client
from twisted.python import log

@defer.inlineCallbacks
def deferMap(job, dataSource, size=1):
    successes = []
    failures = []

    def _cbGather(result, dataUnit, succeeded):
        """This will be called when any download finishes"""
        if succeeded:
            # you could save the file to disk here
            successes.append((dataUnit, result))
        else:
            failures.append((dataUnit, result))

    @apply
    def work():
        for dataUnit in dataSource:
            d = job(dataUnit).addCallbacks(_cbGather, _cbGather,
                callbackArgs=(dataUnit, True),  errbackArgs=(dataUnit, False))
            yield d

    yield defer.DeferredList([task.coiterate(work) for i in xrange(size)])
    defer.returnValue((successes, failures))

def printResults(result):
    successes, failures = result
    print "*** Got %d pages total:" % (len(successes),)
    for url, page in successes:
        print '  * %s -> %d bytes' % (url, len(page))
    if failures:
        print "*** %d pages failed download:" % (len(failures),)
        for url, failure in failures:
            print '  * %s -> %s' % (url, failure.getErrorMessage())

if __name__ == '__main__':
    import sys
    log.startLogging(sys.stdout)
    urls = ['http://twistedmatrix.com',
            'XXX',
            'http://debian.org',
            'http://python.org',
            'http://python.org/foo',
            'https://launchpad.net',
            'noway.com',
            'somedata',
        ]
    pool = deferMap(client.getPage, urls, size=2) # download 2 at once
    pool.addCallback(printResults)
    pool.addErrback(log.err).addCallback(lambda ign: reactor.stop())
    reactor.run()
请注意,我故意包含了一些错误的URL,因此我们可以在结果中看到一些失败:

...
2010-06-29 08:18:04-0300 [-] *** Got 4 pages total:
2010-06-29 08:18:04-0300 [-]   * http://twistedmatrix.com -> 16992 bytes
2010-06-29 08:18:04-0300 [-]   * http://python.org -> 17207 bytes
2010-06-29 08:18:04-0300 [-]   * http://debian.org -> 13820 bytes
2010-06-29 08:18:04-0300 [-]   * https://launchpad.net -> 18511 bytes
2010-06-29 08:18:04-0300 [-] *** 4 pages failed download:
2010-06-29 08:18:04-0300 [-]   * XXX -> Connection was refused by other side: 111: Connection refused.
2010-06-29 08:18:04-0300 [-]   * http://python.org/foo -> 404 Not Found
2010-06-29 08:18:04-0300 [-]   * noway.com -> Connection was refused by other side: 111: Connection refused.
2010-06-29 08:18:04-0300 [-]   * somedata -> Connection was refused by other side: 111: Connection refused.
...

与python有什么联系?您是否需要特定的技术,或者您正在对任何可能的答案进行假设?在线程中下载给定URL的python代码在哪里?然后我们可以改进它,将其限制为N threadsSee,并且,与python有什么联系?您是否需要特定的技术,或者您正在对任何可能的答案进行假设?在线程中下载给定URL的python代码在哪里?然后我们可以改进它,将其限制为N个线程,并且,对于这样一个小东西,有这么多代码!是的,我知道在我的情况下,线程是有用的,因为我可以启动多个下载在同一时间。我将尝试这样做,但是,再一次,我感到惊讶的是,对于这样一个简单的问题@defer、@apply、twisted模块,您使用了许多提示。。。。我认为可以将基本Python与Python分发的模块一起使用。@binoua:代码不多。。。你在问题中粘贴的代码更大。我的代码可以进一步简化,我尽量让它易于理解。另一点:我的代码也是泛型的:泛型deferMap函数可以创建一个池来运行任何返回deferreds的东西@apply是常见的基本老python。Twisted在没有线程的情况下异步执行操作时确实很有帮助,但请注意Twisted是用纯python编写的,不依赖于非python代码。这意味着您可以只使用基本模块来完成它所做的事情,但对于这样一件小事,您只能复制太多的代码!是的,我知道在我的情况下,线程是有用的,因为我可以启动多个下载在同一时间。我将尝试这样做,但是,再一次,我感到惊讶的是,对于这样一个简单的问题@defer、@apply、twisted模块,您使用了许多提示。。。。我认为可以将基本Python与Python分发的模块一起使用。@binoua:代码不多。。。你在问题中粘贴的代码更大。我的代码可以进一步简化,我尽量让它易于理解。另一点:我的代码也是泛型的:泛型deferMap函数可以创建一个池来运行任何返回deferreds的东西@apply是常见的基本老python。Twisted在没有线程的情况下异步执行操作时确实很有帮助,但请注意Twisted是用纯python编写的,不依赖于非python代码。这意味着您可以只使用基本模块来完成它所做的事情,但是您只需要复制这个方法,并考虑活动线程的数量?while True是否消耗CPU?@binoua,这是线程的主体。主程序应为sta
将10个线程进行rt。while True不会烧坏CPU。每个周期从列表中删除一个url。当没有剩余的URL要下载时,每个线程都将退出。你能发布到目前为止你正在使用的代码吗?这个方法考虑了活动线程的数量吗?while True是否消耗CPU?@binoua,这是线程的主体。主程序应该启动10个线程。while True不会烧坏CPU。每个周期从列表中删除一个url。当没有剩余的URL要下载时,每个线程都将退出。你能发布你目前使用的代码吗?