-2

Below is my code to download a YouTube video and then converting it into an audio file. But while renaming it, I am getting an error. Please explain my problem and please provide me a solution.

import os
import tkinter as tk
from tkinter import ttk
from pytube import YouTube
from tkinter.filedialog import askdirectory
from tkinter.messagebox import askyesno, showinfo

This function gives me problem while I am using it to rename my file.

def rename_file(file):
    def return_val():
        print(new_name.get())
        top.destroy()
        return(new_name.get())

    print(file)
    top = tk.Toplevel(root)
    top.title("Rename File")
    top.iconbitmap('icon.ico')
    top.geometry('400x130')

    tk.Label(top, text='Enter new name for the file: ', font='comicsansms 12').grid(row=0, column=0)
    new_name=tk.StringVar()
    new_name.set(file)

    name_entry = ttk.Entry(top, textvariable=new_name, font='comicsansns 12')
    name_entry.focus_force()
    name_entry.grid(row=0, column=1, pady=5)
    
    ttk.Button(top, text='Rename!', command=return_val, width=8).grid(row=3, column=1, pady=18, ipady=9)

This is the main function to download a video from YouTube.

def download_audio():
        try:
            global link_var
            global directory
    
            link = link_var.get() 
    
            yt = YouTube(link)
            title_lable = ttk.Label(root, text=f"Title: {yt.title}", font='lucida 12')
            title_lable.grid(row=3, column=0, pady=9, padx=4)
    
            confirmation = askyesno('Check Title', "Does the title match the video you wanna download?")
    
            if confirmation:
                video = yt.streams.filter(only_audio=True).first()
                video_file = video.download(output_path=directory)
                
                base, ext = os.path.splitext(video_file)
                audio_file = base + '.mp3'
    
                rename = askyesno('Rename File', 'Do you want to rename this file?')
                if rename:                 

Before this function ends,

                   obj = rename_file(audio_file.split('\\')[-1])
                

it moves forward to next line.

                   audio_file = os.path.join(directory, obj)
                   print(audio_file)
    
                os.rename(video_file, audio_file)
                showinfo("Downloaded", "Your Audio file is downloaded")
    
                link_var.set("")
                title_lable.config(text="")

Error:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\user\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__
    return self.func(*args)
  File "f:\Eriq\PYTHON\YT to Mp3 Converter\yttomp3.py", line 53, in download_audio
    audio_file = os.path.join(directory, obj)
  File "C:\Users\user\AppData\Local\Programs\Python\Python37-32\lib\ntpath.py", line 115, in join
    genericpath._check_arg_types('join', path, *paths)
  File "C:\Users\user\AppData\Local\Programs\Python\Python37-32\lib\genericpath.py", line 149, in _check_arg_types
    (funcname, s.__class__.__name__)) from None
TypeError: join() argument must be str or bytes, not 'NoneType'
James Z
  • 12,209
  • 10
  • 24
  • 44
Eriq Codes
  • 18
  • 7
  • 2
    pleas, provide the full traceback of your error. – Guinther Kovalski May 14 '21 at 14:02
  • Always include the complete Traceback - copy and paste it then format it as code (select it and type `ctrl-k`) – wwii May 14 '21 at 14:02
  • I am writing a function that will rename a file in this GUI before it is downloaded. `rename_file` is the function that will help to rename. And it is being executed in the `download_audio` function. And while it takes entry, the `download_audio` function gets completed, even before `rename_file` function completes. – Eriq Codes May 14 '21 at 14:07
  • there is a bit of an issue: there is no point to assign some function to the `command=` if it returns something, that return is unusable, You have to assign that value to a global variable and then use it – Matiiss May 14 '21 at 14:09
  • @wwii I edited my post and pasted the error. – Eriq Codes May 14 '21 at 14:10
  • @Matiiss I know that, but I also wanted to destroy that window, that's why I wrote that function. – Eriq Codes May 14 '21 at 14:12
  • `rename_file` does not have a return statement so it returns `None` - that is assigned to `obj` then it is used as an argument to `os.path.join`. this is a duplicate question - search for `function returns None` – wwii May 14 '21 at 14:15
  • @wwii `rename_file` function have a return function which is in the sub-function `return_val`. Here the error is that before the `rename_file` function ends, it moves forward to the next line (i.e. `audio_file = os.path.join(directory, obj`). – Eriq Codes May 14 '21 at 14:16
  • ok ,You can write that function and destroy the window but just assign the value to a global variable so that it is not lost – Matiiss May 14 '21 at 14:24
  • @Matiiss I just tried that, but it gives: `Traceback (most recent call last): File "C:\Users\user\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__ return self.func(*args) File "f:\Eriq\PYTHON\YT to Mp3 Converter\yttomp3.py", line 56, in download_audio audio_file = os.path.join(directory, name) NameError: name 'name' is not defined` – Eriq Codes May 14 '21 at 14:27
  • ok, did You actually use a global variable? like first of it has to be outside of a function, second since You would be changing it inside a function You would need to use `global` or maybe if You use `global` there is no need to reference it anywhere – Matiiss May 14 '21 at 14:31
  • Thanks for your time, but @acw1668 solved my error. Thank you all. – Eriq Codes May 15 '21 at 08:32

1 Answers1

0

You should make rename_file() act like a modal dialog:

def rename_file(file):
    def return_val():
        print(new_name.get())
        top.destroy()
        # return statement here is useless

    print(file)
    top = tk.Toplevel(root)
    top.title("Rename File")
    top.iconbitmap('icon.ico')
    top.geometry('400x130')

    tk.Label(top, text='Enter new name for the file: ', font='comicsansms 12').grid(row=0, column=0)
    new_name=tk.StringVar()
    new_name.set(file)

    name_entry = tk.Entry(top, textvariable=new_name, font='comicsansns 12')
    name_entry.focus_force()
    name_entry.grid(row=0, column=1, pady=5)

    tk.Button(top, text='Rename!', command=return_val, width=8).grid(row=3, column=1, pady=18, ipady=9)

    root.wait_window(top) # wait for the window to close
    return new_name.get() # return the name entered

Also suggest to use os.path.basename() instead of split() in the following line:

obj = rename_file(audio_file.split('\\')[-1])

So change the above line to:

obj = rename_file(os.path.basename(audio_file))
acw1668
  • 40,144
  • 5
  • 22
  • 34