Python3-在Tkinter中获取cmd的实时输出
我的目标是从shell中的youtube dl获取状态的实时输出,并将其作为标签放到tkinter中。这可能是最糟糕的方法(即使现在不起作用),所以我不介意是否有人想出更好的方法 我试着用另一个问题()做了几件事,但都没有成功Python3-在Tkinter中获取cmd的实时输出,python,python-3.x,tkinter,Python,Python 3.x,Tkinter,我的目标是从shell中的youtube dl获取状态的实时输出,并将其作为标签放到tkinter中。这可能是最糟糕的方法(即使现在不起作用),所以我不介意是否有人想出更好的方法 我试着用另一个问题()做了几件事,但都没有成功 import subprocess import sys import tkinter as tk from threading import Thread master = tk.Tk() link = "https://www.youtube.com/watch?
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()
解决方案:
我需要做一些改变,但杜桑·阿塔纳科维奇的回答起了作用。(我还使用了Textwidget,因为它比标签好得多)
您可以通过两种方式解决这个问题,第一种对YT更好的方法是使用pafy库,pafy的基础是ytdl,所以可以完成,因为我已经完成了,但速度很慢,我现在有了另一个想法,我正在开发,只需稍加修改,就可以将pafy的输出与tkinter wodget连接起来。第二种解决方案是
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 .
sys.stdout.write(…)
很可能不会返回您所认为的结果。也许您应该将结果保存到变量中,然后在调用text\u var.set
之前检查变量以验证其中的内容。嘿,谢谢您的回答。仍然无法获得正确的输出:/调试的第一步始终是验证您的假设。
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 .