Search code examples
pythonpython-3.xyoutubedropboxpytube

Passing a URL through the entry widget (TKinter // Python 3+)


I have been trying to put together a few lines of code that takes a youtube music video URL and converts it to mp3/mp4 + 720p, and then downloads it to my DropBox music folder.

When I'm trying to pass a URL through a TKinter widget (entry bar) I am hitting an error about how the the entry object has no attribute 'type', or that the URL is invalid. Is it something to do with not adding quotation marks to the youtube link or something?

If anyone has any insight I would greatly appreciate it. I assume I'm missing something very obvious, but I can't seem to figure out what exactly.

#!/usr/bin/env python
import sys
import os
import tkinter
from pytube import *
from tkinter import *

top=tkinter.Tk()
yt_variable = StringVar()

def helloCallBack():
    #Select youtube link you want to upload and print contents
    yt = YouTube(yt_entry)
    print(yt.get_videos())
    print(yt.filename)    
    #Set parameters for youtube video
    video = yt.get('mp4', '720p')
    print(yt.videos)
    print("success")

    #Select download location for youtube video
    video.download('C:/Users/coope/Dropbox/BrokenBow/Music/')
    print("Downloaded " + str(yt.filename) + " to " + str(video.download) + " successfully!")
    return

yt_label=tkinter.Label(top,text='Paste Link + Press Go')
yt_label.pack()
yt_button=tkinter.Button(top,text='Go',command= helloCallBack)
yt_button.pack()
yt_entry=tkinter.Entry(top, textvariable=yt_variable)
yt_entry.get()
yt_entry.pack()

top.mainloop()

Solution

  • Briefly, you have the following:

    yt_entry=tkinter.Entry(top, textvariable=yt_variable)
    yt_entry.get()
    yt = YouTube(yt_entry)
    

    You are expecting this to create an Entry widget, retrieve its contents, and send that retrieved value to the YouTube() constructor. It does not work like that. You are actually creating an Entry widget, immediately retrieving its contents, throwing away those contents (which will be empty anyway, since by that point you haven't had a chance to put anything into that field), and then attempting to send the Entry widget itself to the YouTube() constructor.

    On top of that, you give the Entry widget a textvariable, but then you never use it.

    Instead, retrieve the contents of that Entry widget (via its textvariable) within the callback. You can even do it in the YouTube() constructor call.

    ...
    top=tkinter.Tk()
    yt_variable = StringVar()
    
    def helloCallBack():
        ...
        yt = YouTube(yt_variable.get())
        ...
    
    ...
    yt_entry=tkinter.Entry(top, textvariable=yt_variable)
    yt_entry.pack()
    
    top.mainloop()
    

    Since you're not doing anything special with that Entry widget, there's no need for a textvariable at all.

    ...
    top=tkinter.Tk()
    
    def helloCallBack():
        ...
        yt = YouTube(yt_entry.get())
        ...
    
    ...
    yt_entry=tkinter.Entry(top,)
    yt_entry.pack()
    
    top.mainloop()
    

    Also, there's no need for a bare return at the end of a function. It will return regardless once there's nothing more to do, with a default return value of None (the same as what gets returned with a bare return statement, or with return None).