【问题标题】:R reticulate, how do I clear a python object from memory?R网状,如何从内存中清除python对象?
【发布时间】:2017-11-06 20:26:25
【问题描述】:

我通过reticulate 包使用一些python 功能创建了一个函数,特别是使用PIL 打开图像:

image <- "~/Desktop/image.jpg"
pil.image <- reticulate::import( "PIL.Image", convert = FALSE )
img <- pil.image$open( image )

然后我对图像做一些事情(我正在提取几个作物),效果很好。这是我正在做的一个例子(outputs 是我需要的作物数据框,所以crop.grid 只是 4 个数字的向量。

crop.grid <- c( outputs$x.start[x],
                outputs$y.start[x],
                outputs$x.stop[x],
                outputs$y.stop[x] )
crop.grid <- as.integer( crop.grid )
crop.grid <- reticulate::r_to_py( crop.grid )
output.array <- img$crop( box = crop.grid )
output.array$save( output.filename )

在这之后,我想从内存中清除图像(我打开的图像非常大,所以占用大量内存)。我尝试在 python 中关闭图像:

img$close()

以及在 R 中:

rm( img )
gc()

然后用我知道非常小的东西替换这个对象。

img <- reticulate::r_to_py( 1L )

所有这些都运行良好,但我的 RAM 仍然注册为非常满。我对我创建的每个 python 对象都进行了尝试,但唯一能有效清除 RAM 的是重新启动 R 会话。

我知道在python 内我最好使用with 打开图像以便在过程结束时清除它,但我不确定如何使用reticulate 来实现它。


--- 使用类似的python 版本更新:

如果我直接在 python 中执行上述操作:

from PIL import Image
img = Image.open( "/home/user/Desktop/image.jpg" )
output = img.crop( [0,0,100,100] )

然后关闭东西:

output.close()
img.close()

内存被清除。不过,同样的事情在 R 中不起作用。即:

output.array$close()
img$close()
gc() # for good measure

不清除内存。

【问题讨论】:

  • 你有没有试过把它全部包装到with - 像with(pil.image$open( image ) %as% img, { img$crop(r_to_py( c(0,0,100,100)))$save("myfile.jpg") })这样的东西?
  • @lukeA 我没有,但我现在有了。它运行良好,但仍然存在 RAM 已满的问题。有趣的是,加载内存的是 output.array&lt;-img$crop(box=crop.grid) 步骤,但我在函数中重复运行该步骤,并且每次迭代似乎都不会重新读取图像(只有第一次迭代需要大量时间)。关闭 output.arrayrmgc 似乎仍然无法清除 RAM。
  • 也许也可以把它包起来?例如。 with(pil.image$open( image ) %as% img, { with(img$crop(r_to_py( c(0,0,100,100))) %as% output.array, { output.array$save("myfile.jpg") }) }) - 只是试错。
  • 公平呼叫,但仍然没有骰子。我认为with是在R这里操作,所以只删除了R对象。 python 对象(我假设坐在后台环境中)仍然存在。
  • 这不是特定于 reticulate 包的。很有可能您的对象确实被删除了。但是操作系统为 R 提供了内存,即使该内存现在由 R 在内部释放,R 还没有释放它/将它还给操作系统。有很多关于这个的帖子。最简单的解决方案是关闭 R 会话。如果您不想这样做,我经常看到您可以调用 gc 来释放内存,但根据我的经验,这不是让 R 归还 RAM 的可靠方法...

标签: r python-imaging-library reticulate


【解决方案1】:

你需要做三件事:

  1. 在 Python 中显式创建对象:

    py_env <- py_run_string(
        paste(
            "from PIL import Image",
            "img = Image.open('~/Desktop/image.jpg')",
            sep = "\n"
        ),
        convert = FALSE
    )
    img <- py_env$img
    
  2. 图像处理完毕后,首先删除 Python 对象。

    py_run_string("del img")
    
  3. 然后运行 ​​Python 垃圾收集器。

    py_gc <- import("gc")
    py_gc$collect()
    

第 2 步和第 3 步是重要的。第 1 步只是让您有一个要删除的名称。如果有办法删除“隐式”Python 对象(想不出更好的术语),那将节省一些样板文件。

【讨论】:

  • 嗨,内森,非常感谢您的回复。正如我所说,我希望使用reticulate 的更多R 端功能来做到这一点,而不是使用py_run_string。我当然可以用py_run_string 做到这一点,而且由于这里没有答案建议直接解决这个问题,我认为这可能是我需要走的路。我将奖励你赏金,因为你确实提供了一个解决方案,即使它不是我所希望的。不过请注意,我发现在 python 中运行例如 img.close() 似乎会触发垃圾清理,而无需显式调用。
猜你喜欢
  • 2016-04-25
  • 1970-01-01
  • 2011-04-28
  • 2011-02-22
  • 1970-01-01
  • 2021-05-30
  • 1970-01-01
  • 2021-06-27
  • 1970-01-01
相关资源
最近更新 更多