在Linux服务器上,我在python脚本中使用带有 Xvfb 的Chrome / Selenium。有时脚本因其他原因而崩溃,因此,根据我在数字海洋仪表板中看到的情况,随着时间的推移,“Xvfb”的内存消耗最终会增加到近80%。但是,ram增加不一定是由于脚本崩溃,但可能是因为一般情况下释放Xvfb是错误的。
这是我与xvfb相关的内容
from pyvirtualdisplay import Display
..........
display = Display(visible=0, size=(800, 600))
display.start()
//it can crash here doing other things
display.sendstop()
答案 0 :(得分:3)
简短回答是,如果您的代码在您展示的位置崩溃,则不会调用display.sendstop()
。
我认为实现你想要的最“pythonic”方式是使用Display
作为context manager,这意味着你不需要在try /中包装所有代码赶上,但你得到同样的好处。这样的事情应该有效:
import pyvirtualdisplay
with pyvirtualdisplay.Display(visible=0, size=(800, 600)):
// it can crash here doing other things
编辑:在这种特殊情况下调用stop方法很重要的原因(以及为什么你几乎肯定对内存泄漏是正确的)是因为你的代码产生了一个Xvfb子进程来充当虚拟显示。 stop方法终止了这个子进程,所以如果它从未被调用,那么子进程仍在运行&被重新定位到init进程。有关此here的更多信息(“僵尸和孤儿进程”部分)。
我能够使用这一段简单的代码检查其工作原理:
import time
from pyvirtualdisplay import Display
display = Display(visible=0, size=(800, 600))
display.start()
print('About to sleep')
time.sleep(20)
raise Exception('Oh noes!')
display.stop()
然后我在我的shell中运行pstree -sA $(pgrep Xvfb)
(以显示Xvfb进程的进程树)在python脚本崩溃之前和之后。
在崩溃之前,我们可以看到Xvfb进程的父进程是python(其父代是我的shell,其父代是我的终端模拟器等):
systemd---xfce4-terminal---zsh---python---Xvfb-+-{llvmpipe-0}
|-{llvmpipe-1}
|-{llvmpipe-2}
`-{llvmpipe-3}
在python脚本崩溃后,该进程现已被重新分配到init进程(在我的情况下,这是systemd,但在你的情况下,它可能是一些其他的init系统)。
systemd---Xvfb-+-{llvmpipe-0}
|-{llvmpipe-1}
|-{llvmpipe-2}
`-{llvmpipe-3}