导航

几个Python线程坑,和连接池的坑

Posted on 2019-08-07 13:43  李日天  阅读(1247)  评论(0编辑  收藏  举报

urlretrieve 没有超时,需要通过socket来设置 

socket.setdefaulttimeout(10)

而且还需要为他设置连接池,所以直接改用requests来下载文件

def download_file(self, url, filename):
    r = self.session.get(url, stream=True)
    with open(filename, 'wb') as f:
        for chunk in r.iter_content(chunk_size=512):
            if chunk:
                f.write(chunk)

 

 

写原生爬虫遇到问题  can`t start new thread 自己的机器上一直没问题没发现,到了别人的机器上暴漏出来了。

原因是原生的thread在执行完成后并没有销毁退出,而是进入了sleeping状态,导致最后线程创建超出了允许的上限。其实通过修改Thread的初始化中的一些行为,可以使thread可以复用。

或者简单点,使用线程池来解决

from concurrent.futures.thread import ThreadPoolExecutor

def thread_run(target, args_list, max_thread=12):
    with ThreadPoolExecutor(max_thread) as executor:
        for arg in args_list:
            executor.submit(target, arg)

 

还有一个问题就是 Connection pool is full, discarding connection

可以进行如下设置

session.mount(prefix='', adapter=HTTPAdapter(pool_connections=1, pool_maxsize=36, max_retries=1))

但是在多线程情况下还是会出现 pool is full。我把maxsize设置的比 threads数稍大一点时,就没有warning了,也可能是我代码还有隐藏的问题。

 

也可能跟线程池有关,暂时没看 线程池的源码,如果这样可以通过信号量来加锁

from threading import Semaphore

class AA():
    sem = Semaphore(12)
    
    ...

    def getHtml():
        sem.acquire()
        session.get()
        sem.release()