我在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
?
答案 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发送消息,或使用共享内存等。