這是一個簡單的圖形用戶界面。我正在從條目中的用戶那里獲取 url。當按下按鈕時,url被保存在一個檔案中,并呼叫另一個函式通過呼叫(在子行程內)啟動另一個行程。在行程運行時,我想顯示不確定的進度條(直到按下按鈕,該條需要隱藏),當行程完成時,會顯示一條 showinfo 訊息以銷毀 gui。
問題:直到程序完成,該欄才會顯示。顯示 showinfo 對話框后,它才開始進行。意味著,酒吧在它應該真正被摧毀的那一刻開始進步。
我的代碼有什么問題?
import scrapy
import tkinter as tk
from tkinter import messagebox as tkms
from tkinter import ttk
import shlex
from subprocess import call
def get_url():
# get value from entry and write to a file
def scrape():
progress_bar = ttk.Progressbar(root, orient=tk.HORIZONTAL, length=300, mode='indeterminate')
progress_bar.grid(row=3, column=2)
progress_bar.start(10)
command_line = shlex.split('scrapy runspider /media/mayank/Local/Coding/Lab/Scraping/Practices/img.py')
call(command_line)
mes = tkms.showinfo(title='progress', message='Scraping Done')
if mes == 'ok':
root.destroy()
root = tk.Tk()
root.title("Title")
entry1 = tk.Entry(root, width=90, textvariable=url)
entry1.grid(row=0, column=0, columnspan=3)
my_button = tk.Button(root, text="Process", command=lambda: [get_url(), scrape()])
my_button.grid(row=2, column=2)
root.mainloop()
----更新代碼---
import scrapy
import tkinter as tk
from tkinter import messagebox as tkms
from tkinter import ttk
import shlex
from subprocess import call
def get_url():
# get value from entry and write to a file
scrapy = None
def watch():
global scrapy
if scrapy:
if scrapy.poll() != None:
# Update your progressbar to finished.
progress_bar.stop()
progress_bar.destroy()
# Maybe report scrapy.returncode?
print(f'scrapy return code =--######==== {scrapy.returncode}')
scrapy = None
else:
# indicate that process is running.
progress_bar.start(10)
print(f'scrapy return code =--######==== {scrapy.returncode}')
# Re-schedule `watch` to be called again after 0.1 s.
root.after(100, watch)
def scrape():
global scrapy
command_line = shlex.split('scrapy runspider ./img.py')
scrapy = Popen(command_line)
watch()
mes = tkms.showinfo(title='progress', message='Scraping Done')
if mes == 'ok':
root.destroy()
root = tk.Tk()
root.title("Title")
url = tk.StringVar(root)
entry1 = tk.Entry(root, width=90, textvariable=url)
entry1.grid(row=0, column=0, columnspan=3)
my_button = tk.Button(root, text="Process", command=lambda: [get_url(), scrape()])
my_button.grid(row=2, column=2)
progress_bar = ttk.Progressbar(root, orient=tk.HORIZONTAL, length=300, mode='indeterminate')
progress_bar.grid(row=3, column=2)
root.mainloop()
uj5u.com熱心網友回復:
Using會subprocess.call 中斷當前行程,直到被呼叫的行程完成。因此,在呼叫完成之前,GUI 不會更新。
重要提示: 切勿從程式的主執行緒呼叫 或其他便利函式subprocess.run之一。這樣做會凍結 GUI。您應該只從主執行緒創建物件。subprocess.calltkintersubprocess.Popen
您應該做的是創建一個Popen物件,同時禁用開始按鈕。
要跟蹤進度,請定義一個定期呼叫的函式root.after(),例如每 0.1 秒。在此函式中,您可以呼叫該poll()方法來檢查子行程是否已完成。或者,您可以從物件的屬性中設定stdout=subprocess.PIPE和讀取來自子行程的資料。stdoutPopen
下面的代碼是基于您更新的問題的作業(對我而言)示例。請注意,我已scrapy在我的 UNIX 機器上用相對長時間運行的命令替換(我沒有)。由于您將 scrapy 作為子行程運行,因此您不需要import scrapy.
import tkinter as tk
from tkinter import messagebox as tkms
from tkinter import ttk
from subprocess import Popen
proc = None
def watch():
global proc
if proc:
if proc.poll() is not None:
# Update your progressbar to finished.
progress_bar.stop()
progress_bar.destroy()
# Maybe report proc.returncode?
print(f'proc return code =--######==== {proc.returncode}')
proc = None
mes = tkms.showinfo(title='progress', message='Scraping Done')
if mes == 'ok':
root.destroy()
else:
# indicate that process is running.
progress_bar.start(10)
# print(f'proc return code =--######==== {proc.returncode}')
# Re-schedule `watch` to be called again after 0.1 s.
root.after(100, watch)
def scrape():
global proc
command_line = ['netstat']
proc = Popen(command_line)
watch()
root = tk.Tk()
root.title("Title")
url = tk.StringVar(root)
entry1 = tk.Entry(root, width=90, textvariable=url)
entry1.grid(row=0, column=0, columnspan=3)
my_button = tk.Button(root, text="Process", command=lambda: [get_url(), scrape()])
my_button.grid(row=2, column=2)
progress_bar = ttk.Progressbar(root, orient=tk.HORIZONTAL, length=300, mode='indeterminate')
progress_bar.grid(row=3, column=2)
root.mainloop()
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/504270.html
