Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python3-在Tkinter中获取cmd的实时输出_Python_Python 3.x_Tkinter - Fatal编程技术网

Python3-在Tkinter中获取cmd的实时输出

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?

我的目标是从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?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 .