在foreach循环中运行多个子进程?一次一个?

3

我正在创建一个使用subprocess运行rsync并获取stdout并打印输出的Python脚本。 该脚本根据一个配置文件运行多个rsync进程,使用以下代码:

for share in shares.split(', '):
  username = parser.get(share, 'username')
  sharename = parser.get(share, 'name')
  local = parser.get(share, 'local')
  remote = parser.get(share, 'remote')
  domain = parser.get(share, 'domain')
  remotedir = username+"@"+domain+":"+remote
  rsynclog = home + "/.bareshare/"+share+"rsync.log"
  os.system("cp "+rsynclog+" "+rsynclog+".1 && rm "+rsynclog) # MOve and remove old log
  rsync="rsync --bwlimit="+upload+" --stats --progress -azvv -e ssh "+local+" "+username+"@"+domain+":"+remote+" --log-file="+rsynclog+" &"
  # Run rsync of each share
  #         os.system(rsync) 
  self.rsyncRun = subprocess.Popen(["rsync","--bwlimit="+upload,"--stats","--progress","-azvv","-e","ssh",local,remotedir,"--log-file="+rsynclog], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

我认为同时运行多个同步可能不是最好的选择。我该如何设置,使得一个进程完成后再启动下一个进程?
你可以在这里找到我的完整脚本:https://github.com/danielholm/BareShare/blob/master/bareshare.py 另外,我如何让self.rsyncRun在完成后自动停止?当rsync完成所有文件后,它似乎仍在继续,虽然不应该这样做。

请查看Queue模块。 - aganders3
1个回答

4

调用

self.rsyncRun.communicate()

如果你不想阻塞主进程,那么请创建一个线程来处理对subprocess.Popen的调用:


rsyncRun进程完成之前,将阻塞主进程。

import threading

def worker():
    for share in shares.split(', '):
        ...
        rsyncRun = subprocess.Popen(...)
        out, err = rsyncRun.communicate()

t = threading.Thread(target = worker)
t.daemon = True
t.start()
t.join()

抱歉,我不想让主进程等待,只想让rsync进程相互等待。 - Daniel Holm
你可以使用线程模块来生成一个处理对 subprocess.Popen 调用的线程。然后,你可以在该线程中调用 self.rsyncRun.communicate() 而不会阻塞主进程。 - unutbu
所以,我已经添加了这个函数,但我不知道如何从命令中获取输出了? - Daniel Holm
1
如果您愿意等到rsyncRun完成,那么在t.join()之后可以简单地访问outerr。但是,如果您希望看到由rsync命令产生的标准输出和标准错误输出,那么您可能需要使用select.select(或类似的东西)。请参见此SO答案,了解如何执行此操作的示例。 - unutbu
谢谢,我会看一下。编辑:还有一个问题:如何杀死工作进程?即使我发送“gtk.main_quit()”,它仍然在运行。我必须同时单击退出并按Ctrl+C来终止脚本。 - Daniel Holm
1
t.start()之前添加t.daemon = True将导致线程在主进程结束时终止。 - unutbu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接