当交互式绘图在后台运行时如何防止 Python 中的垃圾收集(Python,matplotlib)?
How to prevent garbage collection in Python when an interactive plot runs in the background (Python, matplotlib)?
我有一个使用 matplotlib 和 Button 小部件的代码。
一切正常,但是当将此代码编写为函数时,按钮停止工作。
这是因为函数运行后,按钮对象将被垃圾收集器删除。
这里有一个 代码不能正常工作的例子:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
def fun():
def Prev(x):
print("Prev")
def Next(x):
print("Next")
freqs = np.arange(2, 20, 3)
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.2)
t = np.arange(0.0, 1.0, 0.001)
s = np.sin(2*np.pi*freqs[0]*t)
l, = plt.plot(t, s, lw=2)
axprev = plt.axes([0.7, 0.05, 0.1, 0.075])
axnext = plt.axes([0.81, 0.05, 0.1, 0.075])
bnext = Button(axnext, 'Next')
bnext.on_clicked(Next)
bprev = Button(axprev, 'Previous')
bprev.on_clicked(Prev)
fun()
这是我的不太优雅的解决方案:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
def fun():
def Prev(x):
print("Prev")
def Next(x):
print("Next")
freqs = np.arange(2, 20, 3)
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.2)
t = np.arange(0.0, 1.0, 0.001)
s = np.sin(2*np.pi*freqs[0]*t)
l, = plt.plot(t, s, lw=2)
axprev = plt.axes([0.7, 0.05, 0.1, 0.075])
axnext = plt.axes([0.81, 0.05, 0.1, 0.075])
bnext = Button(axnext, 'Next')
bnext.on_clicked(Next)
bprev = Button(axprev, 'Previous')
bprev.on_clicked(Prev)
return bnext,bprev
b1,b2=fun()
对于此类问题是否有更好的最佳实践解决方案?
正如您正确假设的那样,关键是在外部范围内保持对按钮的引用。如果您不想 return 按钮集合,您可以将按钮添加为图形的属性。对于仅绘制一个图形这样的事情,我不会说有最佳实践,对于更复杂的 UI,可能会有更好的解决方案。但是此代码解决了这个特定问题,而无需显式 returning 按钮引用。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
import matplotlib
matplotlib.use("TkAgg")
def fun():
def Prev(x):
print("Prev")
def Next(x):
print("Next")
freqs = np.arange(2, 20, 3)
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.2)
t = np.arange(0.0, 1.0, 0.001)
s = np.sin(2*np.pi*freqs[0]*t)
l, = plt.plot(t, s, lw=2)
axprev = plt.axes([0.7, 0.05, 0.1, 0.075])
axnext = plt.axes([0.81, 0.05, 0.1, 0.075])
bnext = Button(axnext, 'Next')
bnext.on_clicked(Next)
bprev = Button(axprev, 'Previous')
bprev.on_clicked(Prev)
fig.bnext = bnext # add button references to figure object
fig.bprev = bprev
if __name__ == "__main__":
fun()
plt.show()
我有一个使用 matplotlib 和 Button 小部件的代码。 一切正常,但是当将此代码编写为函数时,按钮停止工作。 这是因为函数运行后,按钮对象将被垃圾收集器删除。
这里有一个 代码不能正常工作的例子:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
def fun():
def Prev(x):
print("Prev")
def Next(x):
print("Next")
freqs = np.arange(2, 20, 3)
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.2)
t = np.arange(0.0, 1.0, 0.001)
s = np.sin(2*np.pi*freqs[0]*t)
l, = plt.plot(t, s, lw=2)
axprev = plt.axes([0.7, 0.05, 0.1, 0.075])
axnext = plt.axes([0.81, 0.05, 0.1, 0.075])
bnext = Button(axnext, 'Next')
bnext.on_clicked(Next)
bprev = Button(axprev, 'Previous')
bprev.on_clicked(Prev)
fun()
这是我的不太优雅的解决方案:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
def fun():
def Prev(x):
print("Prev")
def Next(x):
print("Next")
freqs = np.arange(2, 20, 3)
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.2)
t = np.arange(0.0, 1.0, 0.001)
s = np.sin(2*np.pi*freqs[0]*t)
l, = plt.plot(t, s, lw=2)
axprev = plt.axes([0.7, 0.05, 0.1, 0.075])
axnext = plt.axes([0.81, 0.05, 0.1, 0.075])
bnext = Button(axnext, 'Next')
bnext.on_clicked(Next)
bprev = Button(axprev, 'Previous')
bprev.on_clicked(Prev)
return bnext,bprev
b1,b2=fun()
对于此类问题是否有更好的最佳实践解决方案?
正如您正确假设的那样,关键是在外部范围内保持对按钮的引用。如果您不想 return 按钮集合,您可以将按钮添加为图形的属性。对于仅绘制一个图形这样的事情,我不会说有最佳实践,对于更复杂的 UI,可能会有更好的解决方案。但是此代码解决了这个特定问题,而无需显式 returning 按钮引用。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
import matplotlib
matplotlib.use("TkAgg")
def fun():
def Prev(x):
print("Prev")
def Next(x):
print("Next")
freqs = np.arange(2, 20, 3)
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.2)
t = np.arange(0.0, 1.0, 0.001)
s = np.sin(2*np.pi*freqs[0]*t)
l, = plt.plot(t, s, lw=2)
axprev = plt.axes([0.7, 0.05, 0.1, 0.075])
axnext = plt.axes([0.81, 0.05, 0.1, 0.075])
bnext = Button(axnext, 'Next')
bnext.on_clicked(Next)
bprev = Button(axprev, 'Previous')
bprev.on_clicked(Prev)
fig.bnext = bnext # add button references to figure object
fig.bprev = bprev
if __name__ == "__main__":
fun()
plt.show()