[Python] What is a proper way to renew matplotlib.pyplot figures?

Discussão em 'Python' iniciado por Stack, Março 14, 2025.

  1. Stack

    Stack Membro Participativo

    I am creating multiple figures using a loop with same figure settings, but with different data points on every loop. My problem is that my code is occupying memory on every loop. How do I prevent this?

    Below is the example of my code

    for i in range(len(uniq_tidx)):
    fig,ax = plt.subplots(2,1,figsize=(10,4.5))

    utidx = int(uniq_tidx)

    time_raw = int(itime[utidx])

    tnow = tstd + timedelta(seconds=time_raw)

    yr = tnow.year
    mo = tnow.month
    da = tnow.day
    hr = tnow.hour

    tfmt = "{0:4d}-{1:02d}-{2:02d}-{3:02d}Z".format(yr,mo,da,hr)

    nidx = np.where((itidx == utidx) & (icbs >= cl_thres) & (isst < sst_thres))

    cbs = np.unique(icbs[nidx])[0]
    cos = np.unique(icos[nidx])[0]
    sst = np.mean(isst[nidx])

    lon_all = ilon[iloni[nidx]]
    lat_all = ilat[ilati[nidx]]

    tl = "{0:4d}-{1:02d}-{2:02d} {3:02d}Z\nCluster size = {4:7.2f} km\u00b2 ({5:4d} px), SST = {6:5.2f} K".format(yr,mo,da,hr,cos * qd2km2,cos,sst)

    ofn = "cls.vs.sst.{0:}.{1:s}".format(tfmt,ofmt)
    ofp = "{0:s}/{1:s}".format(odir,ofn)

    print("\t\tofp : {0:s}".format(ofp))

    tb_now = itb_2d [utidx]
    sst_now = isst_2d[utidx]


    # Tb
    bmap = Basemap(**margs,ax=ax[0])
    bmap.drawcoastlines()

    tb_cntf = ax[0].contourf(lons,lats,tb_now,clvls,levels=tb_clvl,cmap="Spectral_r",norm=tb_cmp)
    tb_cb = plt.colorbar(tb_cntf, location="bottom",ax=ax[0],pad=0.05,aspect=50)
    tb_cb.set_label("Tb (K)")


    # SST with scatter points
    bmap = Basemap(**margs,ax=ax[1])
    bmap.drawcoastlines()

    lon_pts,lat_pts = bmap(lon_all,lat_all)

    sst_cntf = ax[1].contourf(lons,lats,sst_now,clvls,levels=sst_clvl,cmap="Spectral_r",norm=sst_cmp)
    ax[1].scatter(lon_pts,lat_pts,10,marker='x',color='k')

    sst_cb = plt.colorbar(sst_cntf, location="bottom",ax=ax[1],pad=0.05,aspect=50)
    sst_cb.set_label("SST (K)")


    plt.subplots_adjust(left=0.024,right=0.992,bottom=0.08,top=0.942,hspace=0.2,wspace=0.2)

    plt.suptitle("{0:s}".format(tl))
    plt.savefig("{0:s}".format(ofp))

    plt.close()



    Above, I am creating fig and ax on every loop, and I am closing the figure by using plt.close(). I tried plt.cla() and matplotlib would complain with an error message of

    RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`). Consider using `matplotlib.pyplot.close()`.


    And the memory leak problem still persists.

    With plt.clf(), I get an error message of

    .
    .
    .
    raise NotImplementedError('cannot remove artist')


    What is a proper way of renewing or reusing a figure and axis object using loops?

    Continue reading...

Compartilhe esta Página