我的 python 安装程序在工作时死机了。我如何解决它?
My python installer freezes while working. How do I fix it?
我用 wxPython 为游戏制作了一个非常简单的 GUI 安装程序。虽然它是用于游戏的,但如果您有 link,从技术上讲它可以用于下载和解压缩任何 zip 文件。问题是当我 运行 GUI 冻结的程序时。它仍然像它应该的那样下载和提取,但 GUI 在发生这种情况时完全冻结。我无法更新文本框或制作下载栏,除非我可以解冻它。我知道为什么它会冻结我只是不知道如何修复它。有人可以帮我吗?
这是我的代码:
import requests, os, sys, zipfile, shutil, subprocess, wx, urllib
url = "{Put any zip file URL here to test the program}"
r = requests.get(url, stream = True)
class Frame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)
myPanel = wx.Panel(self,-1)
myButton = wx.Button(myPanel, -1, 'Download', size=(300,50), pos=(40,350))
myButton.Bind(wx.EVT_LEFT_DOWN, self.onClick)
self.Show(True)
def onClick(self, e):
print ('Clicked')
if os.path.exists("RFMB6_WINDOWS"):
print('\n\nRemoving old RFMP files...')
subprocess.check_call(('attrib -R ' + 'RFMB6_WINDOWS' + '\* /S').split())
shutil.rmtree('RFMB6_WINDOWS')
print('\nRemoved old files.')
else:
pass
print('\n\nDownloading:')
urllib.request.urlretrieve(url, 'RFMP.zip')
print('\nDownload Complete.')
print('\n\nExtracting...')
zip_ref = zipfile.ZipFile("RFMP.zip", 'r')
zip_ref.extractall("RFMB6_WINDOWS")
zip_ref.close()
print('\nExtraction Complete')
print('\n\nCleaning up...')
os.remove("RFMP.zip")
print('\nDone! You have succesfully installed the newest version of the Ravenfield Multiplayer Private Alpha.')
app = wx.App()
frame = Frame(None, wx.ID_ANY, 'Image')
app.MainLoop()
好的,我明白了。正如我所说,我需要对 GUI 进行多线程处理,但当时我想不出来。我现在有。我需要做的是在不同的线程上对 GUI 和我的 'processes' 进行多线程处理。这意味着 GUI(您所看到的)与处理数据(下载、提取等)的线程相比,在一个单独的线程上 运行。
在您使用此代码之前,我想让您知道这不是一个完成的程序。从下载 link 中下载并解压缩 .zip 文件只是最低限度而不冻结。
这是我现在用来解决问题的代码:
# Import libraries
import requests, os, sys, zipfile, shutil, subprocess, wx, urllib, time
from threading import *
# Define variables
url = "Put any zip file URL here to test the program"
r = requests.get(url, stream = True)
# Button definitions
ID_START = wx.NewId()
# Define notification event for thread completion
EVT_RESULT_ID = wx.NewId()
# Check for old files
def Check():
if os.path.exists("Folder"):
print('\n\nRemoving old files...')
subprocess.check_call(('attrib -R ' + 'Folder' + '\* /S').split())
shutil.rmtree('Folder')
print('\nRemoved old files.')
else:
pass
# Download new file
def Download():
print('\n\nDownloading:')
urllib.request.urlretrieve(url, 'temp.zip')
print('\nDownload Complete.')
# Extract new file
def Extract():
print('\n\nExtracting...')
zip_ref = zipfile.ZipFile("temp.zip", 'r')
zip_ref.extractall("Folder")
zip_ref.close()
print('\nExtraction Complete')
# Delete the .zip file but leave the folder
def Clean():
print('\n\nCleaning up...')
os.remove("temp.zip")
print('\nDone!')
# 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
# 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):
"""Run Worker Thread."""
# This is the code executing in the new thread.
Check()
Download()
Extract()
Clean()
# 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, 'GUInstaller',
style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)
self.SetSize(400, 350)
wx.Button(self, ID_START, 'Download', size=(300,50), pos=(42,250))
self.status = wx.StaticText(self, -1, '', pos=(0,200))
self.Bind(wx.EVT_BUTTON, self.OnStart, id=ID_START)
# And indicate we don't have a worker thread yet
self.worker = None
def OnStart(self, event):
"""Start Computation."""
# Trigger the worker thread unless it's already busy
if not self.worker:
self.status.SetLabel('Downloading...')
self.worker = WorkerThread(self)
def OnResult(self, event):
"""Show Result status."""
self.status.SetLabel('Done!')
# The worker is done
self.worker = None
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()
P.S。并非所有这些都是我的代码。我从另一个网站上拿了一个例子,并根据我的需要对其进行了修改。
我用 wxPython 为游戏制作了一个非常简单的 GUI 安装程序。虽然它是用于游戏的,但如果您有 link,从技术上讲它可以用于下载和解压缩任何 zip 文件。问题是当我 运行 GUI 冻结的程序时。它仍然像它应该的那样下载和提取,但 GUI 在发生这种情况时完全冻结。我无法更新文本框或制作下载栏,除非我可以解冻它。我知道为什么它会冻结我只是不知道如何修复它。有人可以帮我吗?
这是我的代码:
import requests, os, sys, zipfile, shutil, subprocess, wx, urllib
url = "{Put any zip file URL here to test the program}"
r = requests.get(url, stream = True)
class Frame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)
myPanel = wx.Panel(self,-1)
myButton = wx.Button(myPanel, -1, 'Download', size=(300,50), pos=(40,350))
myButton.Bind(wx.EVT_LEFT_DOWN, self.onClick)
self.Show(True)
def onClick(self, e):
print ('Clicked')
if os.path.exists("RFMB6_WINDOWS"):
print('\n\nRemoving old RFMP files...')
subprocess.check_call(('attrib -R ' + 'RFMB6_WINDOWS' + '\* /S').split())
shutil.rmtree('RFMB6_WINDOWS')
print('\nRemoved old files.')
else:
pass
print('\n\nDownloading:')
urllib.request.urlretrieve(url, 'RFMP.zip')
print('\nDownload Complete.')
print('\n\nExtracting...')
zip_ref = zipfile.ZipFile("RFMP.zip", 'r')
zip_ref.extractall("RFMB6_WINDOWS")
zip_ref.close()
print('\nExtraction Complete')
print('\n\nCleaning up...')
os.remove("RFMP.zip")
print('\nDone! You have succesfully installed the newest version of the Ravenfield Multiplayer Private Alpha.')
app = wx.App()
frame = Frame(None, wx.ID_ANY, 'Image')
app.MainLoop()
好的,我明白了。正如我所说,我需要对 GUI 进行多线程处理,但当时我想不出来。我现在有。我需要做的是在不同的线程上对 GUI 和我的 'processes' 进行多线程处理。这意味着 GUI(您所看到的)与处理数据(下载、提取等)的线程相比,在一个单独的线程上 运行。
在您使用此代码之前,我想让您知道这不是一个完成的程序。从下载 link 中下载并解压缩 .zip 文件只是最低限度而不冻结。
这是我现在用来解决问题的代码:
# Import libraries
import requests, os, sys, zipfile, shutil, subprocess, wx, urllib, time
from threading import *
# Define variables
url = "Put any zip file URL here to test the program"
r = requests.get(url, stream = True)
# Button definitions
ID_START = wx.NewId()
# Define notification event for thread completion
EVT_RESULT_ID = wx.NewId()
# Check for old files
def Check():
if os.path.exists("Folder"):
print('\n\nRemoving old files...')
subprocess.check_call(('attrib -R ' + 'Folder' + '\* /S').split())
shutil.rmtree('Folder')
print('\nRemoved old files.')
else:
pass
# Download new file
def Download():
print('\n\nDownloading:')
urllib.request.urlretrieve(url, 'temp.zip')
print('\nDownload Complete.')
# Extract new file
def Extract():
print('\n\nExtracting...')
zip_ref = zipfile.ZipFile("temp.zip", 'r')
zip_ref.extractall("Folder")
zip_ref.close()
print('\nExtraction Complete')
# Delete the .zip file but leave the folder
def Clean():
print('\n\nCleaning up...')
os.remove("temp.zip")
print('\nDone!')
# 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
# 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):
"""Run Worker Thread."""
# This is the code executing in the new thread.
Check()
Download()
Extract()
Clean()
# 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, 'GUInstaller',
style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)
self.SetSize(400, 350)
wx.Button(self, ID_START, 'Download', size=(300,50), pos=(42,250))
self.status = wx.StaticText(self, -1, '', pos=(0,200))
self.Bind(wx.EVT_BUTTON, self.OnStart, id=ID_START)
# And indicate we don't have a worker thread yet
self.worker = None
def OnStart(self, event):
"""Start Computation."""
# Trigger the worker thread unless it's already busy
if not self.worker:
self.status.SetLabel('Downloading...')
self.worker = WorkerThread(self)
def OnResult(self, event):
"""Show Result status."""
self.status.SetLabel('Done!')
# The worker is done
self.worker = None
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()
P.S。并非所有这些都是我的代码。我从另一个网站上拿了一个例子,并根据我的需要对其进行了修改。