R中的垃圾收集com对象

时间:2012-08-28 20:31:54

标签: r com garbage-collection

我希望能够从R打开一个excel会话,写入它然后从R关闭excel会话。虽然我可以在同一个函数中完成所有操作,但我试图概括清理代码excel。但是,当我通过传入excel对象从函数调用gc()时,它不会垃圾收集。以下是代码:

opentest<-function() {
    excel<-comCreateObject("Excel.Application")
    comSetProperty(excel,"Visible",T)
    comSetProperty(excel,"DisplayAlerts",FALSE)

    comSetProperty(excel, "SheetsInNewWorkbook", 1)
    wb <- comGetProperty(excel, "Workbooks")
    wb <- comInvoke(wb, "Add")
    excel
}

cleanupexcel<-function(excelobj) {
    comInvoke(excelobj,"Quit")
    rm(excelobj, envir=globalenv()) 
    eapply(env=globalenv(), gc)
}

通过以下函数调用:

excelobj<-  opentest()
cleanupexcel(excelobj)

当我调用上面的两个函数时,我仍然可以看到在我的任务管理器中运行的excel会话。但是,如果我从cleanupexcel()返回后调用gc(),它会成功终止excel会话。

关于如何从通用功能成功获取gc或者我在这里遇到其他问题的任何想法?

1 个答案:

答案 0 :(得分:2)

这是对您的代码的一个小改动应该有效(我现在在Linux上,所以我无法测试它)。 主要的解决方法是将excel实例包装在一个环境中并返回它。

然后,关闭可以访问实例,然后在调用gc()之前将其删除(确保不会引用它):

opentest<-function() {
    excel<-comCreateObject("Excel.Application")
    comSetProperty(excel,"Visible",T)
    comSetProperty(excel,"DisplayAlerts",FALSE)

    comSetProperty(excel, "SheetsInNewWorkbook", 1)
    wb <- comGetProperty(excel, "Workbooks")
    wb <- comInvoke(wb, "Add")

    # wrap excel in an environment
    env <- new.env(parent=emptyenv())
    env$instance <- excel
    env
}

cleanupexcel<-function(excel) {
    comInvoke(excel$instance,"Quit")
    rm("instance", envir=excel)
    gc() 
}

myexcel <- opentest()
cleanupexcel(myexcel)

...请注意,您的旧代码要求将变量命名为“excelobj”,因为您要从cleanupexcel函数中删除它。那不太好。

好的,有很微妙的问题在起作用,所以这里有一个没有excel的可重现的例子:

opentest<-function() {
    excel<-new.env()
    reg.finalizer(excel, function(x) { cat("FINALIZING EXCEL!\n") }, FALSE)

    # wrap excel in an environment
    env <- new.env(parent=emptyenv())
    env$instance <- excel
    env
}

cleanupexcel<-function(excel) {
    cat(excel$instance,"\n")
    rm("instance", envir=excel)
    gc() 
}

myexcel <- opentest()
cleanupexcel(myexcel)
# Prints "FINALIZING EXCEL!"