2017-07-20 76 views
0

私の目標は、シェルのyoutube-dlからのステータスのリアルタイム出力を取得し、それをtkinterのラベルとして配置することです。これはおそらくこれを実行する最悪の方法です(今は動作しない場合でも)。だから、誰かがこれを行うためのよりよい方法を思いついても大丈夫です。Python 3 - Tkinterでcmdのリアルタイム出力を取得する

別の質問(Getting realtime output using subprocess)でいくつか試してみましたが、うまく動作しません。

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() 

ソリューション:

私は少しを変更するために必要な、それは斗山Atanackovićからの回答で働いていました。 pafyライブラリを使用することですあなたはYTのための最初のより良い二つの方法でこの問題を解決することができます

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() 
+1

'sys.stdout.writeです(...) 'あなたが思うものを返すとは思わないでしょう。おそらく、結果を変数に保存して、 'text_var.set'を呼び出す前にその変数を検査してその中にあるものを検証する必要があります。 –

+0

お返事ありがとうございます。それでも正しい出力は得られません。 :/ – HealYouDown

+1

デバッグの最初のステップは、常に前提を検証することです。 –

答えて

1

(それはラベルよりもずっといいですので、私はまたTextwidgetは、使用される)、それは行うことができますので、pafyのベースはytdlです私はそれをしていたが、それは遅かった、と私はi'amが現在開発していること、他のアイデアを得た、そして少しの変更であなたはTkinterのでpafys出力を接続することができますので、wodget.Secondソリューションは

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 . 
関連する問題