Way*_*rts 7 python windows windows-xp subprocess python-2.6
有没有办法终止使用subprocess.Popen类启动的进程,并将"shell"参数设置为"True"?在下面的工作最小示例(使用wxPython)中,您可以愉快地打开和终止记事本进程,但是如果将Popen"shell"参数更改为"True",则记事本进程不会终止.
import wx
import threading
import subprocess
class MainWindow(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title)
self.main_panel = wx.Panel(self, -1)
self.border_sizer = wx.BoxSizer()
self.process_button = wx.Button(self.main_panel, -1, "Start process", (50, 50))
self.process_button.Bind(wx.EVT_BUTTON, self.processButtonClick)
self.border_sizer.Add(self.process_button)
self.main_panel.SetSizerAndFit(self.border_sizer)
self.Fit()
self.Centre()
self.Show(True)
def processButtonClick(self, event):
if self.process_button.GetLabel() == "Start process":
self.process_button.SetLabel("End process")
self.notepad = threading.Thread(target = self.runProcess)
self.notepad.start()
else:
self.cancel = 1
self.process_button.SetLabel("Start process")
def runProcess(self):
self.cancel = 0
notepad_process = subprocess.Popen("notepad", shell = False)
while notepad_process.poll() == None: # While process has not yet terminated.
if self.cancel:
notepad_process.terminate()
break
def main():
app = wx.PySimpleApp()
mainView = MainWindow(None, wx.ID_ANY, "test")
app.MainLoop()
if __name__ == "__main__":
main()
Run Code Online (Sandbox Code Playgroud)
为了这个问题,请接受"shell"必须等于"True".
你为什么用shell=True?
只是不要这样做.你不需要它,它会调用shell而且没用.
我不接受它True,因为它没有.使用shell=True只会带来问题,没有任何好处.不惜一切代价避免它.除非你运行一些shell内部命令,你不需要它,永远.
当使用shell = True并在进程上调用terminate时,实际上是在杀死shell而不是记事本进程.shell将是COMSPEC环境变量中指定的任何内容.
我能想到杀死这个记事本进程的唯一方法是使用Win32process.EnumProcesses()来搜索进程,然后使用win32api.TerminateProcess将其终止.但是,您无法将记事本进程与具有相同名称的其他进程区分开来.
根据 Thomas Watnedal 的回答中给出的提示,他指出示例中实际上只是 shell 被杀死,我根据 Mark Hammond 的 PyWin32 库中给出的示例安排了以下函数来解决我的场景的问题:
procname 是任务管理器中看到的进程名称,不带扩展名,例如 FFMPEG.EXE 将为killProcName("FFMPEG")。请注意,该函数相当慢,因为它执行所有当前正在运行的进程的枚举,因此结果不是即时的。
import win32api
import win32pdhutil
import win32con
def killProcName(procname):
"""Kill a running process by name. Kills first process with the given name."""
try:
win32pdhutil.GetPerformanceAttributes("Process", "ID Process", procname)
except:
pass
pids = win32pdhutil.FindPerformanceAttributesByName(procname)
# If _my_ pid in there, remove it!
try:
pids.remove(win32api.GetCurrentProcessId())
except ValueError:
pass
handle = win32api.OpenProcess(win32con.PROCESS_TERMINATE, 0, pids[0])
win32api.TerminateProcess(handle, 0)
win32api.CloseHandle(handle)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9506 次 |
| 最近记录: |