threading 装饰器实现

创作背景

  • 最近,本菜鸡找到了一个 网站 ,用来追番呀,下载动漫,电影之类的,但有的动漫没有提供下载功能,所以只能 自己下载了呀😏 (dddd)
    在这里插入图片描述

  • 目前 demo 已经做出来了,但还没有封装完成,还有诸多想实现的功能还没有实现

  • 这个是我嫌 下载动漫 的时候速度慢,想开多线程进行 下载 ,但遇到了一些小问题(因为 我很菜,不会多线程),现在算是解决了,写篇博客以供参考


实现过程

target

  • 我想在 进行关键字搜索 的时候使用多线程,然后可以同时搜索多个关键字

实现(部分代码,未修复 bug)

  • 为了说明主要问题,我只粘贴了 部分代码
import requests
import threading
class download_dytt_videos():

    def __init__(self, kw_list):
        self.kw_list = kw_list
        self.headers = {
            'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0'
        }
        self.lock = threading.Lock()

    def _threading(self, func, **kwargs):
        t = threading.Thread(target = func, kwargs = kwargs)
        t.start()
        t.join()

    def search(self):
        '''
        本函数用来搜索关键词,并由用户选择要下载的视频
        :param kw: 要搜索的关键词
        :return: 选择后的视频的简介页的链接
        '''

        for kw in self.kw_list:
            @self._threading
            def kw_search():
                ... # 代码细节
                text = requests.get(
                    url=url,
                    headers=self.headers
                ).text
                ... # 代码细节

出现的问题(已解决)

1. 线程锁问题
  • 如下
    ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。
    urllib3.exceptions.ProtocolError: ('Connection aborted.', ConnectionResetError(10054, '远程主机强迫关闭了一个现有的连接。', None, 10054, None))
    
  • 这个问题出现是因为 线程同步的时候,多个线程同时访问同一数据时,会出现冲突
    • 我这里的问题是 get 请求时加入 hreaders,都使用的 self.hreaders,没有加锁的时候,发生冲突
  • 解决方案:使用线程锁,在进行多线程搜索,进行 get 请求前后 分别加入获得锁和释放锁 ,代码如下(在函数 search 中修改
# 获得锁
self.lock.acquire()
text = requests.get(
	url=url,
	headers=self.headers
).text
# 释放锁,让其他进程使用
self.lock.release()
  • 注:不能在函数 _threading 中加入获得锁和释放锁 ,因为那样就和不加锁一样了,线程同时运行时就会同时要求获得锁,也会产生冲突
2. 装饰器传参问题
  • 我本想 通过装饰器给开启多线程的函数进行传参,比如说,这样的
def _threading(self, func, kw, **kwargs)
  • 但因为自己学的装饰器没有学牢固,一直报错 缺少参数
  • 所以最后使用的上边代码的装饰器
  • 后来我又尝试了一下,可以实现了
  • 代码如下
    def _threading(self, **kwargs):
        def f_threading(func):
            t = threading.Thread(target = func, kwargs = kwargs)
            t.start()
            t.join()
        return f_threading

    def search(self):
        for kw in self.kw_list:
            @self._threading(keyword = kw)
            def kw_search(keyword):
  • 但这样有点麻烦了,因为是在循环中,所以这个函数内的函数 可以直接使用 kw,反正这 都是在函数 search 的内部实现的,外部也调用不了 kw_search 这个函数
  • 意义: 虽然装饰器传参在我这里没有很大的作用,但这也是一种用法,在其他地方有用处,各位可以自己找一下适用的场景,练练手

总结

  • 两个知识点,threading 和 python 装饰器
  • 各位可以自己尝试一下,有什么问题可以给我留言(●’◡’●)



结尾

以上就是我要分享的内容,因为学识尚浅,会有不足,还请各位大佬指正。
有什么问题也可在评论区留言。
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值