如何确定何时以系统(...,wait = FALSE)启动进程已结束

时间:2014-06-16 11:30:44

标签: r

我试图在R中设置异步系统()调用。为了使它有用,用户需要一种方法来检查进程是否已经结束。问题是如何测试?在how to run an executable file and then later kill or terminate the same process with R in Windows中,建议似乎是捕获system()调用之前和之后的所有pid以获取刚刚启动的进程的pid(然后可以用它来测试它是否具有结束),但这似乎是一种容易出错的方式,除了它依赖于操作系统......

是否存在解决此问题的其他方法(不必涉及pid')

编辑:当前场景应该用于:

我正在开发一个Shiny GUI,它可以处理用Java实现的可能非常长时间运行的计算。计算是分批完成的,在这些运行期间,即使R处于空闲状态,GUI也会在等待Java进程完成时被锁定与R服务器进行交互。我想要一种方法来启动Java进程而不是等待它完成(使用wait = FALSE参数),但是有一种故障安全方式来检查它是否已经完成,因此可以相应地更新GUI ... < / p>

2 个答案:

答案 0 :(得分:0)

如果我们愿意调用系统来启动一个进程,那么这个问题似乎简化了如何将PID转换为Windows中刚刚启动的进程。这不是R特定的问题,而是Windows的一般问题。在SO上查看一些答案,我看到one answer that seems reasonable。处理字符串结果,并获得PID。

或者,您可以使用system(...,wait = FALSE)异步启动另一个Rscript,并让它将自己的PID报告回主机进程(通过文件或套接字)。 Rscript可以反过来进行系统调用,然后在系统调用完成后自行终止。然后你只需要观察包装Rscript的PID。这比锁定文件略好,因为您不必依赖已调用的进程来成功完成清理自己的锁定文件。

我对agstudy的解决方案有一些例外(即使它是关键的)。正如ThomasP85所说,你可以通过系统获得异步操作(...,wait = FALSE)。此外,您可以通过套接字获得异步操作,例如svSocketparallel(通过单个节点PSOCK群集)。这些基于套接字的方法中没有任何内容与通过rpy2在python中启动的上述延迟调用的基本不同完成。

答案 1 :(得分:-2)

R甚至不支持多线程系统。所以异步调用它并不是一件容易的事。一种方法是使用支持异步调用的语言调用它。例如python:

  • 使用twisted进行异步操作。
  • 使用rpy2在python函数中调用R调用

这是一个完整的示例,它异步调用2个R函数:

  1. 给定一个半径,它在随机时间睡觉后计算周长
  2. 给定已计算的周长,它会返回原始半径
  3. 这是一个虚拟的例子,但它足够灵活,可以扩展到任何R脚本。

    from twisted.internet.defer import Deferred
    from twisted.internet import reactor
    import rpy2.robjects as robjects
    
     ## define the functions 
     def get_perimeter(r):
         robjects.r('''
            f <- function(r) {
                Sys.sleep(sample(1:3,1))
                2 * pi * r
    
            }
            ''')
        r_f = robjects.r['f']
        print  r_f(r)
        return r_f(r)
    
    def get_radius(p):
        robjects.r('''
            f <- function(p)    p/2 / pi
            ''')
        r_f = robjects.r['f']
        print  r_f(p)
        return r_f(p)
    
    
    def job_done(_):
        from twisted.internet import reactor
        reactor.stop()
    
    ## the asynchronous call 
    d = Deferred()
    d.addCallback(get_perimeter)
    d.addCallback(get_radius)
    d.addCallback(job_done)
    
    
    reactor.callWhenRunning(d.callback, 25410)
    
    reactor.run()
    
相关问题