如何删除R中引用类的方法及其对象

1 投票
1 回答
973 浏览
提问于 2025-04-17 15:34

这个问题会比较长,请大家见谅。

我有一个场景,可能用伪代码来解释会更清楚。

有一个Python文件,叫test.py

def test(i):
    from rpy2.robjects import r
    r.source('r_file.R')
    r.call_function(with some arguments)

    #Some Operations
    del r

还有一个文件,叫r_file.R

rm(list=ls(all=TRUE))

#some global variables
#some reference class

#creating an object of reference class
call_function = function(some arguments)
{
    Do some processing
    call few methods on a reference class

    call some more methods and do some operations

    rm(list=ls(all=TRUE))
    gc()

    return(0)

}

在Python中调用test这个函数时,会传入一些值'i',也就是说这个函数会被多次调用,每次传入的'i'值都大于1,也就是从main中多次调用。因此,我们需要多次加载R文件。我希望每次调用Python函数时,都能启动一个新的R解释器。所以我每次调用函数时都会导入r,并且删除rpy2对象。

在R函数"call_function"中,我调用了一些方法,这些方法又会创建引用类对象。

在R代码的开头和函数some_function退出时,我都使用了rm命令。

有了这些背景,现在我面临的问题是,rm命令并没有删除代码中的任何引用类对象,我总是收到一些警告,比如下面这样:

In .removePreviousCoerce(class1, class2, where, prevIs) :
  methods currently exist for coercing from "Rev_R5" to "envRefClass"; they will be replaced

这里,Rev_R5是一个引用类。我不希望这种情况发生,有没有办法通过rm命令删除所有与引用类相关的方法对象

1 个回答

4

从R的全局环境中删除所有对象,并不意味着你回到了一个全新的R进程(类和方法的定义可能还会保留,就像你发现的那样)。

可以考虑使用R的一些函数,比如 removeClass()removeMethod()removeGeneric,但除非有特别的需求(比如避免重复加载大对象),否则每次创建新的R进程可能是更安全的选择(启动R进程的速度相对较快)。

由于无法终止并重新启动嵌入式的R(这是R本身的限制,而不是rpy2的问题),所以你需要启动和停止嵌入R的Python进程。

一种方法是使用Python的 multiprocessing 包(这个包是Python标准库的一部分)。额外的好处是,这些进程可以并行运行。

下面是一个简单的例子,使用了Doug Hellmann的优秀教程作为基础:

import multiprocessing

def R_worker(i):
    """worker function"""

    print('Worker %i started' % i)
    from rpy2.robjects import r
    r.source('r_file.R')
    r.call_function(with some arguments)

    #Some Operations
    del r
    return

if __name__ == '__main__':
    jobs = []
    for i in range(5):
        p = multiprocessing.Process(target = R_worker, args=(i,))
        jobs.append(p)
        p.start()

撰写回答