使用PySimpleGUI+Pytube时遇AttributeError:'list'对象无'streams'属性
解决YouTube下载器的AttributeError问题
问题描述
我是Python纯新手,之前运行无GUI的Python程序都正常。现在尝试做一个带GUI的YouTube下载器,运行时出现错误:AttributeError: 'list' object has no attribute 'streams',我的代码如下:
import PySimpleGUI as sg from pytube import YouTube import os sg.theme('Reddit') choices = ("MP3", "MP4") yt = YouTube layout = [[sg.Text("Enter URL:"), sg.Input(key='-URL-')], [sg.Listbox(choices, size=(8, len(choices)), key='-CHOICES-')], [sg.Submit(button_color="green"), sg.Cancel(button_color="red")]] window = sg.Window("YouTube Downloader", layout) while True: event, values = window.read() if event in (sg.WIN_CLOSED, 'Cancel'): break elif event == 'Submit': yt = [values['-URL-']] filetype = [values['-CHOICES-']] if "-URL-" == choices[1]: yt = yt.streams.get_highest_resolution() datatype = '.mp4' else: yt = yt.streams.get_audio_only() datatype = '.mp3' destination = "C:\\Users\\Maintain\\Desktop\\testfolder" out_file = yt.download(output_path=destination) base, ext = os.path.splitext(out_file) new_file = base + datatype os.rename(out_file, new_file) sg.popup(yt.title + "has been successfully downloaded.") window.close()
错误原因
- 错误将
yt赋值为列表:yt = [values['-URL-']]这行把yt变成了包含URL的列表,而非pytube.YouTube实例,导致无法调用streams属性 filetype获取错误:sg.Listbox返回的values['-CHOICES-']本身是列表,额外套[]后变成列表的列表,无法正确判断文件类型- 判断逻辑完全错误:
if "-URL-" == choices[1]:的条件毫无意义,应该判断选中的文件类型 - 代码缩进错误:下载逻辑未放在
Submit事件块内,会在窗口关闭后执行,且此时yt可能未正确初始化
修正后的代码
import PySimpleGUI as sg from pytube import YouTube import os sg.theme('Reddit') choices = ("MP3", "MP4") layout = [[sg.Text("Enter URL:"), sg.Input(key='-URL-')], [sg.Listbox(choices, size=(8, len(choices)), key='-CHOICES-')], [sg.Submit(button_color="green"), sg.Cancel(button_color="red")]] window = sg.Window("YouTube Downloader", layout) while True: event, values = window.read() if event in (sg.WIN_CLOSED, 'Cancel'): break elif event == 'Submit': # 创建YouTube实例,而非列表 yt = YouTube(values['-URL-']) # 获取选中的文件类型,Listbox返回列表,取第一个选中项 if not values['-CHOICES-']: sg.popup("请选择下载类型!") continue filetype = values['-CHOICES-'][0] # 根据选中类型获取对应流 if filetype == "MP4": stream = yt.streams.get_highest_resolution() datatype = '.mp4' else: stream = yt.streams.get_audio_only() datatype = '.mp3' # 下载文件 destination = "C:\\Users\\Maintain\\Desktop\\testfolder" out_file = stream.download(output_path=destination) base, ext = os.path.splitext(out_file) new_file = base + datatype os.rename(out_file, new_file) # 弹窗提示下载完成 sg.popup(f"{yt.title} has been successfully downloaded.") window.close()
修正说明
- 删除无用的
yt = YouTube代码,在Submit事件中正确创建YouTube实例 - 正确获取Listbox选中的文件类型,增加未选择类型的提示
- 修正判断条件,根据选中的MP3/MP4获取对应流
- 将所有下载逻辑缩进至
Submit事件块内,确保点击提交后才执行 - 优化弹窗提示的字符串拼接方式,避免遗漏空格
- 新增流变量
stream,避免覆盖yt实例,方便后续获取视频标题
内容的提问来源于stack exchange,提问作者additionalman
相关产品推荐
相关产品推荐

