Python线程没有完成
我目前正在用线程/工作池测试一些东西;我创建了400个线程,总共下载了5000个URL。。。问题是,400个线程中的一些线程“冻结”,当查看我的进程时,我看到每次运行中有+15个线程冻结,经过一段时间后,最终以1比1关闭 我的问题是,是否有一种方法可以让某种“计时器”/“计数器”在x秒后未完成时终止线程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
# 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获取数据时递增整数,并且仅在达到固定重试限制时才将其从字典中删除。捕获套接字错误时:这不起作用吗?