可以从Python杀死Robocopy子进程
在我在Windows上的项目中,我想启动两个目录的镜像。
我知道我可以使用Python看门狗来做到这一点,但是尽管使用Robocopy我会更轻松,更快。
为了简化情况,让我们假设我有一个带有两个按钮的GUI:启动和停止镜像。
以下是带有相关代码的片段:
class MirrorDemon(Thread):
def __init__(self, src, dest) :
self.threading_flag = Event()
self.src = src
self.dest = dest
self.opt = ' /MIR /MON:1 /MOT:1'
self.mirror = None
Thread.__init__(self)
def run(self):
command = 'robocopy {} {} {}'.format(str(self.src),str(self.dest), self.opt)
self.p = subprocess.Popen(command.split(), shell=True)
print(command)
print('start robocopy with PID {}'.format(self.p.pid))
class Window(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
def stop_demon(self):
self.mirror.threading_flag.set()
self.mirror.p.kill()
self.mirror.join()
print('stop demon')
def start_demon(self):
self.mirror = MirrorDemon(Path('./src'), Path('./dest'))
self.mirror.setDaemon(True)
self.mirror.start()
print('start demon')
if __name__ == "__main__":
app = QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec())
当您单击“开始”按钮时,您可以在控制台上打印出PID,如果我在任务列表中检查此PID,则对应于'cmd.exe'进程,并且robocopy启动了它的pid工作。
单击停止时,cmd.exe进程与PID消失相对应,但是背景机器人继续进行!
我尝试了几种变体,但没有运气。
你有一些建议吗?你知道有人找到了解决方案吗?还是实现了镜像看门狗?
感谢
更新
@ulrich的建议后的
,设置shell = false实际上是在做技巧并杀死了Robocopy过程。谢谢!
In my project on windows, I would like to start the mirroring of two directories.
I know that I can use python watchdog to do that, but I though that using robocopy would be easier and faster.
To simplify the situation, let's assume I have a GUI with two buttons: start and stop mirroring.
Here below is a snippet with the relevant code:
class MirrorDemon(Thread):
def __init__(self, src, dest) :
self.threading_flag = Event()
self.src = src
self.dest = dest
self.opt = ' /MIR /MON:1 /MOT:1'
self.mirror = None
Thread.__init__(self)
def run(self):
command = 'robocopy {} {} {}'.format(str(self.src),str(self.dest), self.opt)
self.p = subprocess.Popen(command.split(), shell=True)
print(command)
print('start robocopy with PID {}'.format(self.p.pid))
class Window(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
def stop_demon(self):
self.mirror.threading_flag.set()
self.mirror.p.kill()
self.mirror.join()
print('stop demon')
def start_demon(self):
self.mirror = MirrorDemon(Path('./src'), Path('./dest'))
self.mirror.setDaemon(True)
self.mirror.start()
print('start demon')
if __name__ == "__main__":
app = QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec())
When you click on the start button, you get a PID print out on the console and if I check this PID in the tasklist it corresponds to 'cmd.exe' process and the robocopy starts its job.
When you click on stop, the cmd.exe process corresponding to the PID disappers, but the background robocopy continues!!
I have tried several variations, but no luck.
Do you have some advises? Do you know if somebody has found a solution? Or maybe implemented a mirroring watchdog?
thanks
Update
Following the the suggestion of @Ulrich, setting shell=False is actually doing the trick and killing the robocopy process.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
通过更改以下方式:
对此:
...您确保该过程将直接从当前过程启动,而无需启动新的外壳过程以启动它。
您返回的PID是用于Shell过程的,并且您可以杀死外壳,而无需从该外壳发起的杀死过程。通过不在新的外壳中启动它,您要回来的PID就是实际过程的PID,您可以按预期杀死它。
AS 文档在Windows上指定是您希望执行的命令已内置在shell中(例如,您不需要
shell = true
运行一个批处理文件或基于控制台的可执行文件。”By changing this:
To this:
... you're ensuring that the process will be started directly from the current process, without starting a new shell process to start it in.
The PID you were getting back was for the shell process, and you can kill the shell without killing processes launched from that shell. By not starting it in a new shell, the PID you're getting back is the PID of the actual process and you'll be able to kill it as expected.
As the documentation states: "The only time you need to specify
shell=True
on Windows is when the command you wish to execute is built into the shell (e.g. dir or copy). You do not needshell=True
to run a batch file or console-based executable."