Reputation: 156
my goal is to get realtime output of the status from youtube-dl in shell and put it as label in tkinter. This is probably the worst way of doing this (even if it doesn't work right now), so I don't mind if someone come up with a better way to do this.
I tried a few things with another question (Getting realtime output using subprocess), but I don't get it to work.
import subprocess
import sys
import tkinter as tk
from threading import Thread
master = tk.Tk()
link = "https://www.youtube.com/watch?v=AC-3RJHzEU8"
def start_thread():
t = Thread(target = download)
t.start()
def download():
global text_var
cmd = "youtube-dl -x --audio-format mp3 {0}".format(link)
process = subprocess.Popen(cmd,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell = True)
while True:
out = process.stdout.read(1)
if out == '' and process.poll() != None:
break
if out != '':
text_var.set(sys.stdout.write(out.decode('utf-8')))
sys.stdout.flush()
text_var = tk.StringVar()
text_var.set("Status")
tk.Button(master, text = "Download", command = start_thread).pack()
tk.Label(master, textvariable = text_var).pack()
tk.mainloop()
I needed to change a bit, but it worked with the answer from Dušan Atanacković. (I also used a Textwidget, because it's way better than a label)
import subprocess
import tkinter as tk
from threading import Thread
master = tk.Tk()
def sudo(cmd, terminal):
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=1, universal_newlines=True, shell = True)
p.poll()
while True:
line = p.stdout.readline()
terminal.insert(tk.END, line)
terminal.see(tk.END)
if not line and p.poll is not None: break
while True:
err = p.stderr.readline()
terminal.insert(tk.END, err)
terminal.see(tk.END)
if not err and p.poll is not None: break
terminal.insert(tk.END, '\n Finished download')
textfield = tk.Text(master, font = "Arial 15")
textfield.pack()
link = "https://www.youtube.com/watch?v=s8XIgR5OGJc"
a = "youtube-dl --extract-audio --audio-format mp3 '{0}'".format(link)
t = Thread(target = lambda: sudo(a, textfield))
t.start()
tk.mainloop()
Upvotes: 0
Views: 1266
Reputation: 444
You can solve this in two ways, first better for YT is to use pafy library, base of pafy is ytdl so it can be done since i had made that but it was slow, and i got another idea that i'am developing now, and with little modification you can connect pafys output with tkinter wodget.Second solution is
def sudo(self, cmnd, terminal, top): # 1
sudo_password = 'your sudo code' + '\n'
sudos = ['sudo', '-S']
terminal.delete('1.0', END)
for item in eval(cmnd):
cmd = sudos + item.split()
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=1, universal_newlines=True)
p.stdin.write(sudo_password)
p.poll()
while True:
line = p.stdout.readline()
terminal.insert(END, line)
terminal.see(END)
top.updates()
if not line and p.poll is not None: break
while True:
err = p.stderr.readline()
terminal.insert(END, err)
terminal.see(END)
top.updates()
if not err and p.poll is not None: break
terminal.insert(END, '\n * END OF PROCESS *')
cmnd - list of commands you want to execute, ['youtube-dl some link'], with even one command it should be LIST
terminal - thats Text widget in my app, but you can use any wiget as well, only you would have to change all lines terminal.insert(END, 'some text') to terminal.insert(0, 'some text') - END to 0
top is scrollbar container for my app which you can remove if you don't need it
of course you have to provide root=Tk(), parents and other containers for the terminal widget .
Upvotes: 1