Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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_Threadpool - Fatal编程技术网

Python线程没有完成

Python线程没有完成,python,multithreading,threadpool,Python,Multithreading,Threadpool,我目前正在用线程/工作池测试一些东西;我创建了400个线程,总共下载了5000个URL。。。问题是,400个线程中的一些线程“冻结”,当查看我的进程时,我看到每次运行中有+15个线程冻结,经过一段时间后,最终以1比1关闭 我的问题是,是否有一种方法可以让某种“计时器”/“计数器”在x秒后未完成时终止线程 # download2.py - Download many URLs using multiple threads. import os import urllib2 import worke

我目前正在用线程/工作池测试一些东西;我创建了400个线程,总共下载了5000个URL。。。问题是,400个线程中的一些线程“冻结”,当查看我的进程时,我看到每次运行中有+15个线程冻结,经过一段时间后,最终以1比1关闭

我的问题是,是否有一种方法可以让某种“计时器”/“计数器”在x秒后未完成时终止线程

# download2.py - Download many URLs using multiple threads.
import os
import urllib2
import workerpool
import datetime
from threading import Timer

class DownloadJob(workerpool.Job):
    "Job for downloading a given URL."
    def __init__(self, url):
        self.url = url # The url we'll need to download when the job runs
    def run(self):
        try:
            url = urllib2.urlopen(self.url).read()
        except:
            pass

# Initialize a pool, 400 threads in this case
pool = workerpool.WorkerPool(size=400)

# Loop over urls.txt and create a job to download the URL on each line
print datetime.datetime.now()
for url in open("urls.txt"):
    job = DownloadJob(url.strip())
    pool.put(job)

# Send shutdown jobs to all threads, and wait until all the jobs have been completed
pool.shutdown()
pool.wait()
print datetime.datetime.now()

urlopen接受一个超时值,我认为这是处理它的最佳方式

但我同意评论员的观点,400个线程可能太多了

问题是,400个线程中的一些正在“冻结”

这很可能是因为这条线

url = urllib2.urlopen(self.url).read()
默认情况下,Python将永远等待远程服务器响应,因此,如果某个URL指向忽略该数据包的服务器,或者该服务器速度非常慢,则该线程可能永远被阻塞

您可以使用的
timeout
参数设置线程等待远程主机响应的时间限制

url = urllib2.urlopen(self.url, timeout=5).read() # Time out after 5 seconds
…或者您可以通过将这些行放在代码的顶部来全局设置它

import socket
socket.setdefaulttimeout(5) # Time out after 5 seconds

您是否进行了一些分析,以确定400个线程是否真的在提高您的性能?线不是自由的;每个线程都有一些开销,理想的线程数量可能远远少于这个。我试着看看用5、100、200和400个线程处理5000个URL需要多少时间200是最快的。它工作得很好!谢谢。但是,当我这样做的时候,URL将永远不会被下载,我应该添加什么代码以便再次尝试URL(如果可能的话,使用短代码)?@Coryza由于代码的多线程性质,这有点复杂。一种快速的方法是创建一个全局列表,并将url附加到
块中的列表中,但
块除外(因为列表附加是线程安全的)。一旦
pool.wait()
返回,您可以重复失败的列表,或者将其转储到文件中,记住这些URL将来可能永远不会工作。@Coryza在回复您删除的注释时,它可能会工作,但同样,某些URL可能永远不会工作,因此您的程序可能永远不会终止。您可以使用将URL映射为整数的字典,每次尝试从URL获取数据时递增整数,并且仅在达到固定重试限制时才将其从字典中删除。捕获套接字错误时:这不起作用吗?