如何停止QThread "gracefully"?
How to stop QThread "gracefully"?
我得到了一些帮助来完成以下代码。但是我需要从 Worker 线程中的这个循环中跳出,所以当我退出应用程序时,它不会崩溃。目前,当我退出应用程序时,QThread 仍然是 运行。
如果我使用 break 语句,它会起作用,但我无法再搜索主机,因为循环已完全关闭。我尝试了几种方法来做到这一点,但没有运气。我是编程新手。
class Worker(QThread):
found = Signal(str)
notFound = Signal(str)
def __init__(self):
QThread.__init__(self)
self.queue = Queue()
def run(self):
while True:
hostname = self.queue.get()
output_text = collect_host_status(hostname)
for i in output_text:
if "not found" in i:
self.notFound.emit(i.replace(" not found", ""))
else:
self.found.emit(i)
def lookUp(self, hostname):
self.queue.put(hostname)
class MainWindow(QMainWindow):
def __init__(self):
# ...
self.ui.pushButton_2.clicked.connect(self.buttonclicked)
self.thread = Worker()
self.thread.found.connect(self.ui.textEdit_2.append)
self.thread.notFound.connect(self.ui.textEdit_3.append)
self.thread.start()
def buttonclicked(self):
if self.ui.textEdit.toPlainText():
self.thread.lookUp(self.ui.textEdit.toPlainText())
收集主机状态的代码如下:
def get_brss_host_status(host):
host = host.lower()
api_url = 'https://some.system.with/api/'
host_search = 'status/host/{}?format=json'.format(host)
r = requests.get(api_url + host_search, auth=(loc_brss_user, loc_brss_passwd))
request_output = r.text
if request_output == '{"error":"Not Found","full_error":"Not Found"}':
host2 = host.upper()
host_search2 = 'status/host/{}?format=json'.format(host2)
r2 = requests.get(api_url + host_search2, auth=(loc_brss_user, loc_brss_passwd))
request_output2 = r2.text
# print('Debug request_output2', request_output2)
if request_output and request_output2 == '{"error":"Not Found","full_error":"Not Found"}':
output_string = host + " not found"
else:
output_string = host2
else:
output_string = host
return output_string
def collect_host_status(hosts):
hosts_list = list(hosts.split("\n"))
status_list = []
for i in hosts_list:
host = get_brss_host_status(i)
status_list.append(host)
return status_list
正如@ekhumoro 在评论中所建议的那样,基本解决方案是在 while 循环中使用一个简单的标志,这将确保一旦循环重新开始,如果不遵守条件,它就会退出。
不过,应注意两个重要方面:
- 使用队列的基本
get()
使循环无限等待;
- 如果出现任何网络问题(临时网络问题等),示例中的功能(网络请求)可能会延迟一段时间;
要正确解决这些问题,应进行以下修改:
get()
应该使用超时,这样即使没有请求在排队,它也允许退出循环;作为替代方案,您可以取消设置“运行”标志,将任何内容添加到队列并在继续之前检查标志:这确保您不必等待队列 get()
超时;
- 网络请求也应该有一个最小超时时间;
- 它们应该从线程单独完成,而不是分组,这样如果请求的主机列表太大并且您想在查找时退出,线程可以退出;
from queue import Queue, Empty
class Worker(QThread):
found = Signal(str)
notFound = Signal(str)
def __init__(self):
QThread.__init__(self)
self.queue = Queue()
def run(self):
self.keepRunning = True
while self.keepRunning:
hostList = self.queue.get()
if not self.keepRunning:
break
# otherwise:
# try:
# hostList = self.queue.get(timeout=1)
# except Empty:
# continue
for hostname in hostList.splitlines():
if not self.keepRunning:
break
if hostname:
output_text = get_brss_host_status(hostname)
if output_text is None:
continue
if "not found" in output_text:
self.notFound.emit(output_text.replace(" not found", ""))
else:
self.found.emit(output_text)
def stop(self):
self.keepRunning = False
self.queue.put(None)
def lookUp(self, hostname):
self.queue.put(hostname)
并在 get_brss_host_status
中更改以下内容:
def get_brss_host_status(host):
host = host.lower()
api_url = 'https://some.system.with/api/'
host_search = 'status/host/{}?format=json'.format(host)
try:
r = requests.get(api_url + host_search,
auth=(loc_brss_user, loc_brss_passwd),
<b>timeout=1</b>)
except Timeout:
return
# ...
我得到了一些帮助来完成以下代码。但是我需要从 Worker 线程中的这个循环中跳出,所以当我退出应用程序时,它不会崩溃。目前,当我退出应用程序时,QThread 仍然是 运行。 如果我使用 break 语句,它会起作用,但我无法再搜索主机,因为循环已完全关闭。我尝试了几种方法来做到这一点,但没有运气。我是编程新手。
class Worker(QThread):
found = Signal(str)
notFound = Signal(str)
def __init__(self):
QThread.__init__(self)
self.queue = Queue()
def run(self):
while True:
hostname = self.queue.get()
output_text = collect_host_status(hostname)
for i in output_text:
if "not found" in i:
self.notFound.emit(i.replace(" not found", ""))
else:
self.found.emit(i)
def lookUp(self, hostname):
self.queue.put(hostname)
class MainWindow(QMainWindow):
def __init__(self):
# ...
self.ui.pushButton_2.clicked.connect(self.buttonclicked)
self.thread = Worker()
self.thread.found.connect(self.ui.textEdit_2.append)
self.thread.notFound.connect(self.ui.textEdit_3.append)
self.thread.start()
def buttonclicked(self):
if self.ui.textEdit.toPlainText():
self.thread.lookUp(self.ui.textEdit.toPlainText())
收集主机状态的代码如下:
def get_brss_host_status(host):
host = host.lower()
api_url = 'https://some.system.with/api/'
host_search = 'status/host/{}?format=json'.format(host)
r = requests.get(api_url + host_search, auth=(loc_brss_user, loc_brss_passwd))
request_output = r.text
if request_output == '{"error":"Not Found","full_error":"Not Found"}':
host2 = host.upper()
host_search2 = 'status/host/{}?format=json'.format(host2)
r2 = requests.get(api_url + host_search2, auth=(loc_brss_user, loc_brss_passwd))
request_output2 = r2.text
# print('Debug request_output2', request_output2)
if request_output and request_output2 == '{"error":"Not Found","full_error":"Not Found"}':
output_string = host + " not found"
else:
output_string = host2
else:
output_string = host
return output_string
def collect_host_status(hosts):
hosts_list = list(hosts.split("\n"))
status_list = []
for i in hosts_list:
host = get_brss_host_status(i)
status_list.append(host)
return status_list
正如@ekhumoro 在评论中所建议的那样,基本解决方案是在 while 循环中使用一个简单的标志,这将确保一旦循环重新开始,如果不遵守条件,它就会退出。
不过,应注意两个重要方面:
- 使用队列的基本
get()
使循环无限等待; - 如果出现任何网络问题(临时网络问题等),示例中的功能(网络请求)可能会延迟一段时间;
要正确解决这些问题,应进行以下修改:
get()
应该使用超时,这样即使没有请求在排队,它也允许退出循环;作为替代方案,您可以取消设置“运行”标志,将任何内容添加到队列并在继续之前检查标志:这确保您不必等待队列get()
超时;- 网络请求也应该有一个最小超时时间;
- 它们应该从线程单独完成,而不是分组,这样如果请求的主机列表太大并且您想在查找时退出,线程可以退出;
from queue import Queue, Empty
class Worker(QThread):
found = Signal(str)
notFound = Signal(str)
def __init__(self):
QThread.__init__(self)
self.queue = Queue()
def run(self):
self.keepRunning = True
while self.keepRunning:
hostList = self.queue.get()
if not self.keepRunning:
break
# otherwise:
# try:
# hostList = self.queue.get(timeout=1)
# except Empty:
# continue
for hostname in hostList.splitlines():
if not self.keepRunning:
break
if hostname:
output_text = get_brss_host_status(hostname)
if output_text is None:
continue
if "not found" in output_text:
self.notFound.emit(output_text.replace(" not found", ""))
else:
self.found.emit(output_text)
def stop(self):
self.keepRunning = False
self.queue.put(None)
def lookUp(self, hostname):
self.queue.put(hostname)
并在 get_brss_host_status
中更改以下内容:
def get_brss_host_status(host):
host = host.lower()
api_url = 'https://some.system.with/api/'
host_search = 'status/host/{}?format=json'.format(host)
try:
r = requests.get(api_url + host_search,
auth=(loc_brss_user, loc_brss_passwd),
<b>timeout=1</b>)
except Timeout:
return
# ...