Python 启动函数,因为线程不会 join/end
Python start function as thread won't join/end
我目前遇到线程连接问题。我有一个函数,它根据给定的参数执行一系列操作。有一个 "start" 按钮可以启动函数,这个函数得到 运行 作为一个线程。
同一个按钮变成了 "stop" 按钮,单击时将停止该功能。不幸的是,线程似乎并没有结束。
相关代码在这里...注意"self.stop_com_loop"是用来结束线程的...
如有意见将不胜感激。
def Start_Com(self):
"""
Start Com Funtion
"""
self.AppendText("\n-----------------Start Communication to Modbus-----------------\n")
self.stop_com_loop = False
cmd = ("modpoll.exe -p 504 -1 192.168.1.100")
self.AppendText("Executing Command: %s" %(cmd))
while(not self.stop_com_loop):
self._runcommand(cmd)
time.sleep(1)
self.logging_cb.Enable(True)
self.ping_btn.Enable(True)
self.com_btn.SetLabel(START_COM_STR)
self.AppendText("\n-----------------End Communication to Modbus-----------------\n")
print("Why Won't I die?")
def _com_evt(self,
evt):
"""
Com Button Event
"""
if self.com_btn.GetLabelText() == START_COM_STR:
self.logging_cb.Enable(False)
self.ping_btn.Enable(False)
self.com_btn.SetLabel(STOP_COM_STR)
self.com_thread = threading.Thread(target=self.Start_Com)
self.com_thread.daemon = True
self.com_thread.start()
elif self.com_btn.GetLabelText() == STOP_COM_STR:
self.stop_com_loop = True
# self.com_thread.join() # When this line is inserted. System Hangs
while(True):
print self.com_thread
print self.com_thread.isAlive()
if not self.com_thread.isAlive():
break
time.sleep(1)
self.com_btn.SetLabel(START_COM_STR)
else:
self.AppendText("Unknown Start Com Button State")
def _runcommand(self,
cmd):
"""
Run Command given and output to text control
"""
self.error_occured = False
cmd_l = cmd.split(" ")
self.pjob = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
stdin=subprocess.PIPE,
bufsize=0,
creationflags = subprocess.CREATE_NEW_PROCESS_GROUP)
while True:
line = self.pjob.stdout.readline()
skip_line = False
for token in self.DO_NOT_PRINT_TOKEN_L:
if ((token in line)):
skip_line = True
if skip_line:
continue
wx.Yield()
if line.strip() == "":
pass
elif self.ERROR_COM_TOKEN in line:
self.error_occured = True
self.AppendText("%-30s~ ERROR: %s\n" %(self.GetTime(),
line.strip()))
else:
self.AppendText("%-30s~ %s" %(self.GetTime(),
line.strip()))
if not line: break
# Print that error occured and when error resolves
if self.error_occured:
self.AppendText("\nXXXXXXXXXXXXXXXXXXXXX %% ERROR OCCURED %% XXXXXXXXXXXXXXXXXXXXX\n")
self.last_one_was_error = True
self.AppendOverviewText("%-30s~ %% ERROR OCCURED %% "
%(self.GetTime()))
else:
if self.last_one_was_error:
self.AppendText("\n+++++++++++++++++++++ ** ERROR RESOLVED ** +++++++++++++++++++++\n")
self.AppendOverviewText("%-30s~ ** ERROR RESOLVED ** "
%(self.GetTime()))
self.last_one_was_error = False
self.pjob.wait()
self.pjob = None
编辑:
我已经隔离到似乎阻止线程加入的行... AppendText 函数似乎阻止线程加入。我不知道为什么。
初始化logging_ctrl
self.logging_ctrl = wx.TextCtrl(self, -1, "",
style=wx.TE_MULTILINE | wx.TE_READONLY)
AppendText 方法:
def AppendText(self,
text):
"""
Append text to logging text control and file is logging is enabled
"""
self.logging_ctrl.AppendText(str(text) + '\n')
您不能在线程中使用大多数 wx
调用。 wx
图形例程只能从主线程调用。
为了解决这个问题,有一个安全的 wx.CallAfter()
方法允许从线程注册操作。
在您的 AppendText
方法中,只需执行以下操作:
def AppendText(self,
text):
"""
Append text to logging text control and file is logging is enabled
"""
wx.CallAfter(self.logging_ctrl.AppendText,str(text) + '\n')
如果你在主线程中,那将和以前一样。在其他线程中,它将避免您遇到的锁定,因为它只是记下要执行的操作,而 wx mainloop 会处理它。您可能看不到图形方面的差异,但您的线程将正确退出。
我目前遇到线程连接问题。我有一个函数,它根据给定的参数执行一系列操作。有一个 "start" 按钮可以启动函数,这个函数得到 运行 作为一个线程。
同一个按钮变成了 "stop" 按钮,单击时将停止该功能。不幸的是,线程似乎并没有结束。
相关代码在这里...注意"self.stop_com_loop"是用来结束线程的...
如有意见将不胜感激。
def Start_Com(self):
"""
Start Com Funtion
"""
self.AppendText("\n-----------------Start Communication to Modbus-----------------\n")
self.stop_com_loop = False
cmd = ("modpoll.exe -p 504 -1 192.168.1.100")
self.AppendText("Executing Command: %s" %(cmd))
while(not self.stop_com_loop):
self._runcommand(cmd)
time.sleep(1)
self.logging_cb.Enable(True)
self.ping_btn.Enable(True)
self.com_btn.SetLabel(START_COM_STR)
self.AppendText("\n-----------------End Communication to Modbus-----------------\n")
print("Why Won't I die?")
def _com_evt(self,
evt):
"""
Com Button Event
"""
if self.com_btn.GetLabelText() == START_COM_STR:
self.logging_cb.Enable(False)
self.ping_btn.Enable(False)
self.com_btn.SetLabel(STOP_COM_STR)
self.com_thread = threading.Thread(target=self.Start_Com)
self.com_thread.daemon = True
self.com_thread.start()
elif self.com_btn.GetLabelText() == STOP_COM_STR:
self.stop_com_loop = True
# self.com_thread.join() # When this line is inserted. System Hangs
while(True):
print self.com_thread
print self.com_thread.isAlive()
if not self.com_thread.isAlive():
break
time.sleep(1)
self.com_btn.SetLabel(START_COM_STR)
else:
self.AppendText("Unknown Start Com Button State")
def _runcommand(self,
cmd):
"""
Run Command given and output to text control
"""
self.error_occured = False
cmd_l = cmd.split(" ")
self.pjob = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
stdin=subprocess.PIPE,
bufsize=0,
creationflags = subprocess.CREATE_NEW_PROCESS_GROUP)
while True:
line = self.pjob.stdout.readline()
skip_line = False
for token in self.DO_NOT_PRINT_TOKEN_L:
if ((token in line)):
skip_line = True
if skip_line:
continue
wx.Yield()
if line.strip() == "":
pass
elif self.ERROR_COM_TOKEN in line:
self.error_occured = True
self.AppendText("%-30s~ ERROR: %s\n" %(self.GetTime(),
line.strip()))
else:
self.AppendText("%-30s~ %s" %(self.GetTime(),
line.strip()))
if not line: break
# Print that error occured and when error resolves
if self.error_occured:
self.AppendText("\nXXXXXXXXXXXXXXXXXXXXX %% ERROR OCCURED %% XXXXXXXXXXXXXXXXXXXXX\n")
self.last_one_was_error = True
self.AppendOverviewText("%-30s~ %% ERROR OCCURED %% "
%(self.GetTime()))
else:
if self.last_one_was_error:
self.AppendText("\n+++++++++++++++++++++ ** ERROR RESOLVED ** +++++++++++++++++++++\n")
self.AppendOverviewText("%-30s~ ** ERROR RESOLVED ** "
%(self.GetTime()))
self.last_one_was_error = False
self.pjob.wait()
self.pjob = None
编辑: 我已经隔离到似乎阻止线程加入的行... AppendText 函数似乎阻止线程加入。我不知道为什么。
初始化logging_ctrl
self.logging_ctrl = wx.TextCtrl(self, -1, "",
style=wx.TE_MULTILINE | wx.TE_READONLY)
AppendText 方法:
def AppendText(self,
text):
"""
Append text to logging text control and file is logging is enabled
"""
self.logging_ctrl.AppendText(str(text) + '\n')
您不能在线程中使用大多数 wx
调用。 wx
图形例程只能从主线程调用。
为了解决这个问题,有一个安全的 wx.CallAfter()
方法允许从线程注册操作。
在您的 AppendText
方法中,只需执行以下操作:
def AppendText(self,
text):
"""
Append text to logging text control and file is logging is enabled
"""
wx.CallAfter(self.logging_ctrl.AppendText,str(text) + '\n')
如果你在主线程中,那将和以前一样。在其他线程中,它将避免您遇到的锁定,因为它只是记下要执行的操作,而 wx mainloop 会处理它。您可能看不到图形方面的差异,但您的线程将正确退出。