【发布时间】:2023-03-10 08:15:01
【问题描述】:
很简单的问题。如何让这个程序在“run()”函数完成 5 秒后退出?
# Import Libraries
import requests, os, sys, zipfile, shutil, subprocess, wx, urllib, time
from threading import *
# Define variables
url = "Insert any Dropbox .zip file link here"
r = requests.get(url, stream = True)
myEVT_PROGRESS = wx.NewEventType() # Custom Event Type
EVT_PROGRESS = wx.PyEventBinder(myEVT_PROGRESS, 1) # bind specific events to event handlers
# Button definitions
ID_START = wx.NewId()
# Define notification event for thread completion
EVT_RESULT_ID = wx.NewId()
# Downloads new file
def Download():
urllib.request.urlretrieve(url, 'File.zip')
# Extracts new file
def Extract():
zip_ref = zipfile.ZipFile("File.zip", 'r')
zip_ref.extractall("Folder")
zip_ref.close()
# Deletes the .zip file but leave the folder
def Clean():
os.remove("File.zip")
class ProgressEvent(wx.PyCommandEvent):
"""Event to signal that a status or progress changed"""
def __init__(self, etype, eid, status=None, progress=None):
"""Creates the event object"""
wx.PyCommandEvent.__init__(self, etype, eid)
self._status = status # field to update label
self._progress = progress # field to update progress bar
def GetValue(self):
"""Returns the value from the event.
@return: the tuple of status and progress
"""
return (self._status, self._progress)
# Thread class that executes processing
class WorkerThread(Thread):
"""Worker Thread Class."""
def __init__(self, notify_window):
"""Init Worker Thread Class."""
Thread.__init__(self)
self._notify_window = notify_window
self.setDaemon(1)
# This starts the thread running on creation.
self.start()
# This is what runs on a separate thread when you click the download button
def run(self):
# This is the code executing in the new thread.
self.sendEvent('Checking for old files...', 00)
self.sendEvent('Checking for old files...', 100)
time.sleep(.5)
if os.path.exists("Folder"):
self.sendEvent('Removing old files...', 200)
subprocess.check_call(('attrib -R ' + 'Folder' + '\\* /S').split())
shutil.rmtree('Folder')
time.sleep(.3)
self.sendEvent('Removed old files!', 300)
else:
time.sleep(.3)
self.sendEvent('No old files found.', 300)
time.sleep(.3)
pass
self.sendEvent('Downloading Package...', 400)
Download()
self.sendEvent('Downloading complete!', 600)
time.sleep(.3)
self.sendEvent('Extracting...', 650)
Extract()
self.sendEvent('Extraction complete!', 900)
time.sleep(.3)
self.sendEvent('Cleaning up...', 950)
Clean()
time.sleep(.3)
self.sendEvent('Cleaning complete!', 1000)
time.sleep(.3)
self.sendEvent('Done!',
1000)
time.sleep(5)
######### QUIT PROGRAM HERE #########
def sendEvent(self, status=None, progress=None):
# Send event to main frame, first param (str) is for label, second (int) for the progress bar
evt = ProgressEvent(myEVT_PROGRESS, -1, status, progress)
wx.PostEvent(self._notify_window, evt)
# GUI Frame class that spins off the worker thread
class MainFrame(wx.Frame):
"""Class MainFrame."""
def __init__(self, parent, id):
"""Create the MainFrame."""
wx.Frame.__init__(self, parent, id, 'RFMP GUInstaller',
style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER
^ wx.MAXIMIZE_BOX)
self.SetSize(400, 350)
wx.Button(self, ID_START, 'Download', size=(300,50), pos=(42,250))
self.Bind(wx.EVT_BUTTON, self.OnStart, id=ID_START)
self.status = wx.StaticText(self, -1, '', pos=(7,200), style=wx.NO_BORDER)
self.status.SetBackgroundColour((255,255,0)) # set text back color
self.gauge = wx.Gauge(self, range = 1000, size = (370, 30), pos=(7,217),
style = wx.GA_HORIZONTAL)
# And indicate we don't have a worker thread yet
self.worker = None
self.Bind(EVT_PROGRESS, self.OnResult) # Bind the custom event to a function
def OnStart(self, event):
# Trigger the worker thread unless it's already busy
if not self.worker:
self.status.SetLabel('')
self.worker = WorkerThread(self)
def OnResult(self, event):
"""Our handler for our custom progress event."""
status, progress = event.GetValue()
self.status.SetLabel(status)
if progress:
self.gauge.SetValue(progress)
class MainApp(wx.App):
"""Class Main App."""
def OnInit(self):
"""Init Main App."""
self.frame = MainFrame(None, -1)
self.frame.Show(True)
self.SetTopWindow(self.frame)
return True
# Main Loop
if __name__ == '__main__':
app = MainApp(0)
app.MainLoop()
显然,我需要添加更多细节,因为我的程序中有很多代码,所以我在这里做了一个不必要的长句子,以使我的帖子看起来更具描述性,以满足需要我制作的堆栈溢出网站的要求我的代码更具描述性,否则它不会让我发布我需要帮助修复的很长的代码,因为我昨天才开始编写 GUI python。
【问题讨论】:
标签: python python-3.x multithreading user-interface wxpython