You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 09:36:23