Python应用中如何实现youtube-dl同时下载3个视频?
实现多进程并发下载的几种方案
我来给你几个实用的方案,不用复杂的多线程也能实现同时下载3个视频的需求:
方案一:手动用subprocess管理后台进程
os.system是阻塞式的,执行完一个命令才会继续下一个,而subprocess.Popen可以非阻塞启动子进程。我们可以手动维护一个进程列表,控制同时运行的进程数不超过3:
import subprocess import time # 假设你的视频数据是这样的结构 videos = [ {"path": "/path/to/video1.mp4", "url": "http://example.com/video1"}, {"path": "/path/to/video2.mp4", "url": "http://example.com/video2"}, # 更多视频... ] email = "your_email@example.com" password = "your_password" running_processes = [] max_concurrent = 3 for v in videos: # 先清理已经完成的进程 running_processes = [proc for proc in running_processes if proc.poll() is None] # 如果当前运行的进程数小于3,启动新的下载 while len(running_processes) >= max_concurrent: time.sleep(1) running_processes = [proc for proc in running_processes if proc.poll() is None] # 用列表形式传递命令参数,避免字符串拼接的安全问题 cmd = [ "youtube-dl", "-u", email, "-p", password, "-o", v["path"], v["url"] ] proc = subprocess.Popen(cmd) running_processes.append(proc) print(f"启动下载:{v['url']}") # 等待最后一批进程完成 for proc in running_processes: proc.wait()
注意:用列表形式传递命令参数比字符串拼接更安全,能避免路径含空格或特殊字符导致的错误,也能防范shell注入风险。
方案二:借助shell工具控制并发(需要系统支持)
如果你的系统安装了parallel或xargs这类工具,可以用它们来轻松控制并发数,代码会更简洁:
用parallel的例子:
import subprocess import tempfile videos = [ {"path": "/path/to/video1.mp4", "url": "http://example.com/video1"}, # 更多视频... ] email = "your_email@example.com" password = "your_password" # 生成所有下载命令 commands = [] for v in videos: # 注意给含空格的路径加引号 cmd = f'youtube-dl -u "{email}" -p "{password}" -o "{v["path"]}" {v["url"]}' commands.append(cmd) # 把命令写入临时文件 with tempfile.NamedTemporaryFile(mode='w', delete=False) as f: f.write('\n'.join(commands)) # 用parallel启动3个并发任务 subprocess.run(["parallel", "-j", "3", "--", "sh", "-c", "{}"], stdin=open(f.name))
用xargs的例子:
# 前面的命令生成部分和上面一样 subprocess.run(["xargs", "-P", "3", "-I", "{}", "sh", "-c", "{}"], stdin=open(f.name))
注意:如果是Windows系统,可能需要额外安装这些工具(比如通过WSL或Chocolatey),Linux/macOS一般默认有xargs,parallel可能需要手动安装。
方案三:用Python原生的ProcessPoolExecutor
如果你不想手动管理进程,也可以用Python的concurrent.futures.ProcessPoolExecutor,它会自动帮你控制并发进程数,代码更简洁:
from concurrent.futures import ProcessPoolExecutor import subprocess def download_video(v, email, password): cmd = [ "youtube-dl", "-u", email, "-p", password, "-o", v["path"], v["url"] ] # 用subprocess.run阻塞执行单个下载任务 subprocess.run(cmd, check=True) print(f"完成下载:{v['url']}") videos = [ {"path": "/path/to/video1.mp4", "url": "http://example.com/video1"}, # 更多视频... ] email = "your_email@example.com" password = "your_password" # 设置最大并发数为3 with ProcessPoolExecutor(max_workers=3) as executor: for v in videos: executor.submit(download_video, v, email, password)
额外提示
- 尽量避免在命令行明文传递密码,可以考虑用
youtube-dl的配置文件(比如~/.config/youtube-dl/config)来存储认证信息,格式如下:
这样命令里就不需要带-u your_email@example.com -p your_password-u和-p参数了,更安全。 - 如果下载过程中出现网络问题,可以给
youtube-dl加--retries参数增加重试次数。
内容的提问来源于stack exchange,提问作者user3541631
相关产品推荐
相关产品推荐

