从python线程调用的进程在关闭主进程时继续运行

时间:2015-10-28 08:59:43

标签: python tkinter

我在Tkinter上写了一个robocopy.exe包装器,代码组织如下: -

Tkinter Wrapper:

  • 生成一个新线程并传递参数,其中包括源/目标和其他参数

(注意:Queue对象也传递给线程,因为线程将从robocopy读取输出并将放入queue,主tkinter线程将继续轮询{{ 1}}并将使用输出更新Tkinter文本小部件

代码段

queue

主题(在单独的文件中)

以下是线程

的代码段
... Code to poll queue and update tk widget ...

q = Queue.Queue()
t1 = threading.Thread(target=CopyFiles,args=(q,src,dst,), kwargs={"ignore":ignore_list})
t1.daemon = True
t1.start()

关闭tkinter应用程序时调用的代码: -

def CopyFiles(q,src,dst,ignore=None):
    extra_args =  ['/MT:15', '/E', '/LOG:./log.txt', '/tee', '/r:2', '/w:2']
    if len(ignore) > 0:
        extra_args.append('/xf')
        extra_args.extend(ignore)
        extra_args.append('/xd')
        extra_args.extend(ignore)
    command_to_pass = ["robocopy",src, dst]
    command_to_pass.extend(extra_args)
    proc = subprocess.Popen(command_to_pass,stdout=subprocess.PIPE)
    while True:
      line = proc.stdout.readline()
      if line == '':
        break
      q.put(line.strip())

问题

每当我在def onQuit(self): global t1 if t1.isAlive(): pass if tkMessageBox.askyesno("Title", "Do you really want to exit?"): self.destroy() self.master.destroy() 运行时关闭tkinter应用程序,python应用程序关闭但robocopy继续运行。

我已尝试将线程设置为守护程序,但它没有任何效果。如何在调用robocopy.exe方法时停止robocopy.exe

1 个答案:

答案 0 :(得分:0)

为了简化事情,让我们忽略Tkinter以及使用单独线程这一事实。

情况是你的应用程序产生一个子进程来执行一个外部程序(在这个问题中 robocopy.exe ),你需要从你的应用程序中停止生成的程序特定事件(当Tkinter应用程序在此问题中结束时)。

这需要一个进程间通信机制,因此生成的进程将被通知该事件,并作出相应的反应。一种常见的机制是使用操作系统提供的信号。

您可以向外部进程发送信号(SIGTERM)并要求它退出。假设程序按预期对信号做出反应(编写得最好的应用程序),您将获得所需的行为(该过程将终止)。

在子进程上使用terminate方法将当前平台的正确信号发送到子进程。

你需要在proc函数中引用子进程对象onQuit(从提供的代码我看到onQuit是一个函数而不是对象方法,所以它可以使用全局变量来访问proc),因此您可以调用该过程的terminate方法:

def onQuit(self):
    global t1, proc
    if t1.isAlive():
        pass
    # by the way I'm not sure about the logic, but I guess this
    # below statement should be an elif instead of if
    if tkMessageBox.askyesno("Title", "Do you really want to exit?"):
        proc.terminate()
        self.destroy()
        self.master.destroy()

此代码假定您在全局范围内存储对子流程的引用,因此您还必须修改CopyFiles

我不确定 robocopy 如何处理终止信号,我猜这不是我们可以控制的东西。

如果您对外部程序有更多控制权(可以修改源代码),则可能有更多选项,例如使用stdio发送消息,或使用共享内存等。