使用pafy多线程获取YouTube视频流时随机出现ImportError问题求助
问题原因
Python的模块导入流程本身不是线程安全的。你使用的pafy库不会在首次import pafy的时候就加载后端依赖,而是在第一次调用pafy.new()的时候才动态导入pafy.backend_youtube_dl模块。当多个线程同时触发这个动态导入逻辑时,就会出现某个线程尝试导入还未完成初始化的模块,进而触发你遇到的循环导入报错,这也是为什么报错线程完全随机的原因。
解决方案
两种方案任选其一即可解决问题,优先推荐方案1,不会影响后续多线程的并行执行效率:
- 方案1:主线程提前触发一次模块导入
启动所有子线程之前,先在主线程里调用一次pafy.new(),确保后端模块在多线程运行前已经完成初始化,修改后的代码如下:
import pafy import threading def get_playurl(url): video = pafy.new(url) best = video.getbest() playurl = best.url return playurl # 新增:主线程提前触发后端模块导入,避免多线程同时导入的冲突 pafy.new("https://www.youtube.com/watch?v=erG5rgNYSdk") threads = [] for i in range(5): t = threading.Thread(target=get_playurl, args=("https://www.youtube.com/watch?v=erG5rgNYSdk&ab_channel=WeezerVEVO",)) t.start() threads.append(t) for thread in threads: thread.join()
- 方案2:给pafy.new调用加锁
如果不方便提前调用的话,可以创建一个线程锁,所有线程调用pafy.new的时候先获取锁,保证同一时间只有一个线程在执行导入逻辑,修改如下:
import pafy import threading # 新建锁对象 pafy_lock = threading.Lock() def get_playurl(url): # 调用pafy.new前加锁,避免同时导入 with pafy_lock: video = pafy.new(url) best = video.getbest() playurl = best.url return playurl threads = [] for i in range(5): t = threading.Thread(target=get_playurl, args=("https://www.youtube.com/watch?v=erG5rgNYSdk&ab_channel=WeezerVEVO",)) t.start() threads.append(t) for thread in threads: thread.join()
内容的提问来源于stack exchange,提问作者michael
相关产品推荐
相关产品推荐

