通过Python subprocess调用yt-dlp下载YouTube视频,Ubuntu下报FileNotFoundError
问题:Ubuntu系统中使用subprocess调用yt-dlp报错FileNotFoundError
尝试通过Python的subprocess.Popen调用yt-dlp下载YouTube视频,脚本在Windows运行正常,但Ubuntu下出现以下错误:
Traceback (most recent call last): File "/home/purelogics/Arslan/shorts_bot/moveis/movies.py", line 17, in <module> download_video() File "/home/purelogics/Arslan/shorts_bot/moveis/movies.py", line 13, in download_video downloading = subprocess.Popen(command + URL) File "/home/linuxbrew/.linuxbrew/Cellar/python@3.10/3.10.8/lib/python3.10/subprocess.py", line 971, in __init__ self._execute_child(args, executable, preexec_fn, close_fds, File "/home/linuxbrew/.linuxbrew/Cellar/python@3.10/3.10.8/lib/python3.10/subprocess.py", line 1847, in _execute_child raise child_exception_type(errno_num, err_msg, err_filename) FileNotFoundError: [Errno 2] No such file or directory: 'yt-dlp https://www.youtube.com/watch?v=C_rsdqKA6ok'
原代码如下:
import subprocess from moviepy.editor import * import os import moviepy.editor as mp # Download files through url and saves it in yt-vidoes dir command = "yt-dlp " URL = 'https://www.youtube.com/watch?v=C_rsdqKA6ok' parameters = ' --output yt-videos/%(title)s' def download_video(): downloading = subprocess.Popen(command + URL) downloading.wait() print(downloading.returncode) download_video()
解决方案
问题根源
Windows系统中,subprocess.Popen默认会把字符串参数交给cmd解析,能正确识别命令和参数;但Linux系统中,若不指定shell=True,会把整个字符串当作单个可执行文件路径去查找,自然找不到名为yt-dlp https://xxx的文件,因此报错。
修复步骤
推荐使用subprocess官方建议的列表参数形式(避免shell注入风险,兼容性更好),同时完善代码逻辑:
- 确保输出目录存在,防止下载失败
- 将命令、参数、URL拆分为列表元素传入
Popen - 若yt-dlp不在系统PATH中,使用绝对路径(可通过
which yt-dlp命令查看路径)
修改后的代码:
import subprocess from moviepy.editor import * import os import moviepy.editor as mp # Download files through url and saves it in yt-videos dir command = "yt-dlp" # 去掉末尾空格,避免参数混乱 URL = 'https://www.youtube.com/watch?v=C_rsdqKA6ok' # 参数拆分为列表,每个参数/参数值单独作为元素 parameters = ['--output', 'yt-videos/%(title)s'] def download_video(): # 确保输出目录存在,不存在则创建 os.makedirs('yt-videos', exist_ok=True) # 用列表拼接命令、参数、URL downloading = subprocess.Popen([command] + parameters + [URL]) downloading.wait() print(downloading.returncode) download_video()
备选方案(不推荐)
如果一定要用字符串形式调用,需添加shell=True参数,但这种方式存在shell注入风险,且若URL/参数包含特殊字符可能出错:
def download_video(): os.makedirs('yt-videos', exist_ok=True) full_command = f"{command} {parameters.strip()} {URL}" downloading = subprocess.Popen(full_command, shell=True) downloading.wait() print(downloading.returncode)
额外检查
如果仍报错,先在Ubuntu终端运行yt-dlp --version确认命令可执行,若提示找不到命令,需重新安装yt-dlp或使用绝对路径(比如command = "/usr/local/bin/yt-dlp")。
内容的提问来源于stack exchange,提问作者Arslan Khalid
相关产品推荐
相关产品推荐

