gpt4 book ai didi

python - 当应用程序退出时,使用 Python subprocess 模块启动的进程不会被终止

转载 作者:太空宇宙 更新时间:2023-11-03 18:19:28 25 4
gpt4 key购买 nike

当我退出应用程序(代码如下)时,我使用 subprocess.Popen 启动的两个 ping 进程不会自动终止,并且仍然显示在 Windows 7 任务列表中。

当应用程序运行时,ping 进程在 Python.exe 下显示为两个线程。当应用程序退出时,这两个进程将移动到系统进程选项卡并继续在那里运行。

我该如何解决这个问题?我希望在我的应用程序关闭时终止这两个 ping 进程。

# -*- coding: utf-8 -*- 

import sys
import time
import subprocess
from threading import Thread
import re
from PyQt4.QtGui import QMainWindow, QApplication, QStandardItemModel, QStandardItem, QWidget, QVBoxLayout, QTableView
from PyQt4.QtCore import pyqtSignature, Qt, QTimer, SIGNAL, QString, QMetaObject
from Queue import Queue

try:
_fromUtf8 = QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s

class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(500, 435)
self.centralWidget = QWidget(MainWindow)
self.centralWidget.setObjectName(_fromUtf8("centralWidget"))
self.verticalLayout = QVBoxLayout(self.centralWidget)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.tableView = QTableView(self.centralWidget)
self.tableView.setObjectName(_fromUtf8("tableView"))
self.verticalLayout.addWidget(self.tableView)
MainWindow.setCentralWidget(self.centralWidget)

self.retranslateUi(MainWindow)
QMetaObject.connectSlotsByName(MainWindow)

def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QApplication.translate("MainWindow", "Ping Tester", None, QApplication.UnicodeUTF8))

if sys.platform.startswith('linux'):
getdata = re.compile(r"icmp_req=(\d+) ttl=(\d+) time=([\d\.]+)\sms")
pingstr = ["ping", "-n", "-i 0.2"]
filtered = "Packet filtered"
delaytime = 200
else:
getdata = re.compile(r"=([\d\.]+)ms TTL=(\d+)")
pingstr = ["ping.exe", "-t"]
timeout = "Request timed out."
delaytime = 500

try:
with open("ips.conf", "r") as f:
t_node = f.read().decode('utf-8')
if not t_node:
raise IOError
except IOError:
with open("ips.conf", "w") as f:
t_node = u"""
8.8.8.8-Google
184.22.112.34-USAHE
"""
f.write(t_node.encode('utf-8'))

node = []
for line in t_node.split('\n'):
try:
ip, desc = line.strip().split("-")
node.append((ip, desc))
except ValueError:
pass
nodecount = len(node)

class MainWindow(QMainWindow, Ui_MainWindow):
"""
Class documentation goes here.
"""
def __init__(self, parent = None):
"""
Constructor
"""
QMainWindow.__init__(self, parent)
self.setupUi(self)
self.model = QStandardItemModel()
self.model.setColumnCount(6)
self.model.setRowCount(nodecount)
self.model.setHorizontalHeaderLabels(["IP", "Description", "Loss%", "CurPing", "AvgPing", "TTL"])
for i, (ip, desc) in enumerate(node):
self.setitem(i, 0, ip)
self.setitem(i, 1, desc)
self.setitem(i, 2, "")
self.setitem(i, 3, "")
self.setitem(i, 4, "")
self.setitem(i, 5, "")
self.tableView.setModel(self.model)
for i in range(len(node)):
self.tableView.setRowHeight(i, 18)
self.resizetable()
self.timer = QTimer(self)
self.connect(self.timer,
SIGNAL("timeout()"),
self.checkitems)
self.timer.start(delaytime)

def checkitems(self):
while not q.empty():
item = q.get()
self.chgtxt(*item)
q.task_done()
self.resizetable()

def resizetable(self):
self.tableView.resizeColumnsToContents()

def chgtxt(self, x, y, value):
self.model.item(x, y).setText(value)

def setitem(self, x, y, value):
self.model.setItem(x, y, QStandardItem(value))

app = QApplication(sys.argv)
ui = MainWindow()
ui.show()
q = Queue()

def pinger(i, ip, desc):
s = ""
avgping = 0
count = 0
timeoutcount = 0
ret = subprocess.Popen(pingstr + [ip],
stdout=subprocess.PIPE)
while True:
try:
s += ret.stdout.read(1)

tryfind = getdata.findall(s)
if sys.platform.startswith('linux'):
if len(tryfind) > 0:
req, ttl, crtping = tryfind[-1]
avgping += float(crtping)
count += 1
q.put((i, 3, crtping + "ms"))
q.put((i, 4, "%.2f" % (avgping * 1.0 / count) + "ms"))
q.put((i, 5, ttl))
q.put((i, 2, "%.2f" % ((int(req) - count) * 100.0 / int(req))))
s = ""
elif filtered in s:
q.put((i, 2, "Failed"))
q.put((i, 3, "Failed"))
q.put((i, 4, "Failed"))
q.put((i, 5, "Failed"))
ret.kill()
s = ""
else:
if len(tryfind) > 0:
crtping, ttl = tryfind[-1]
avgping += float(crtping)
count += 1
q.put((i, 3, crtping + "ms"))
q.put((i, 4, "%.2f" % (avgping * 1.0 / count) + "ms"))
q.put((i, 5, ttl))
q.put((i, 2, "%.2f" % (timeoutcount * 100.0 / (count + timeoutcount))))
elif timeout in s:
timeoutcount += 1
q.put((i, 2, "-"))
q.put((i, 3, "-"))
if count:
q.put((i, 5, "%.2f" % (timeoutcount * 100.0 / (count + timeoutcount))))
else:
q.put((i, 5, "-"))
s = ""
except IOError:
print s
break

def startworkers():
for i, (ip, desc) in enumerate(node):
worker = Thread(target=pinger, args=(i, ip, desc))
worker.setDaemon(True)
worker.start()
time.sleep(delaytime / 10000.0)

startthread = Thread(target=startworkers)
startthread.setDaemon(True)
startthread.start()

sys.exit(app.exec_())

最佳答案

这是一种使用 atexit 的方法:

import subprocess
from threading import Thread
import sys
import atexit

from PyQt4.QtGui import QMainWindow, QApplication

class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(("MainWindow"))
MainWindow.resize(500, 435)

def runproc():
p = subprocess.Popen(["sleep", "500"])
atexit.register(kill_proc, p)
p.communicate()

def kill_proc(proc):
try:
proc.terminate()
except Exception:
pass

class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.resize(300, 300)

if __name__ == "__main__":
app = QApplication(sys.argv)
ui = MainWindow()
ui.show()
for i in range(0, 3):
t = Thread(target=runproc)
t.start()
sys.exit(app.exec_())

每个线程都会注册一个 atexit 回调,该回调传递它创建的 Popen 对象。当进程通过正常方式退出时,atexit 处理程序将被调用,并且在每个处理程序中,我们都会对 Popen 对象调用 terminate,从而终止该进程。请注意,这不会处理有人向您的进程发送 SIGKILL 之类的信号;它仅通过关闭 QMainWindow 来退出,或者通过 CLI 运行时执行 Ctrl+C 之类的操作。

编辑:

要处理关闭时出现的异常,您必须更改代码处理从子进程的 stdout 读取的数据的方式。当您在关闭时终止子进程时,它们会将 None 发送到其 stdout,并且您的线程会尝试处理该 None,就好像它是实际数据一样。您只需要优雅地处理这种情况即可:

out = ret.stdout.read(1)
if not out:
break
s += out
print s
tryfind = getdata.findall(s)

关于python - 当应用程序退出时,使用 Python subprocess 模块启动的进程不会被终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24410518/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com