我编写了一些代码来处理一组文件,将它们拼接在一起并绘制成图。代码的大致流程如下:
- 遍历指定目录下的所有文件和子目录。
- 在每个子目录中,查找并提取符合特定命名规则的数据文件。
- 从每个数据文件中读取数据并进行一些处理,包括数据拆分、噪声消除等。
- 将处理后的数据绘制成频谱图、时域图和频域图。
- 将绘制的图像保存到指定路径。
代码在运行一段时间后会占用大量的内存,最终导致程序崩溃。经过调查,发现问题出在数据处理和绘图的过程中,其中可能存在内存泄漏。
2、解决方案
2.1 减少不必要的变量
在代码中,我发现了一些不必要的变量被创建并在内存中保存,即使它们不再被使用。例如,在绘制频谱图时,我使用了一个名为 spec1 的变量来存储频谱图数据,但在绘图结束后,我并没有释放这个变量,导致它一直驻留在内存中。
2.2 及时释放内存
在使用完变量或对象后,我应该及时释放它们占用的内存。例如,在读取完一个数据文件后,我可以使用 del 语句来删除不再需要的变量,以便操作系统回收这些内存。
2.3 使用缓存技术
在某些情况下,如果需要对大量数据进行重复处理,可以使用缓存技术来减少内存的使用。例如,在绘制时域图时,我需要对数据进行傅里叶变换。我可以将傅里叶变换的结果缓存起来,这样在绘制其他时域图时,就可以直接从缓存中获取结果,而无需重新计算。
2.4 使用内存分析工具
可以使用内存分析工具来帮助查找内存泄漏的问题。例如,在 Python 中,可以使用 memory_profiler 库来分析内存的使用情况,并找出哪些变量或对象占用了过多的内存。
代码示例
以下是我对部分代码进行修改后的示例:
import gc
for paths, dirs, files in os.walk(start_path):
for d in dirs:
path = start_path + changedir + d
pathpart = d
os.chdir(path)
for file in glob.glob("*-0.dat"):
tempname = file.split("-")
fileName1 = str(tempname[0] + "-" + tempname[1]+ "-")
gc.collect()
Chan2 = []
Chan1 = []
temp_1 = []
temp_2 = []
temp_3 = []
Data_Sets1 = []
Data_Sets2 = []
Headers = []
for fileNumber in range(0,45):
fileName = fileName1 + str(fileNumber) + fileName3
header, data1, data2 = u.unpackFile(path,fileName)
if header == None:
logging.warning("curropted file found at " + fileName)
Data_Sets1.append(temp_1)
Data_Sets2.append(temp_2)
Headers.append(temp_3)
temp_1 = []
temp_2 = []
temp_3 = []
else:
logging.info(fileName + " is good!")
temp_3.append(header)
for i in range(0,10000):
temp_1.append(data1[i])
temp_2.append(data2[i])
Data_Sets1.append(temp_1)
Data_Sets2.append(temp_2)
Headers.append(temp_3)
temp_1 = []
temp_2 = []
temp_3 = []
del temp_1
del temp_2
del temp_3
lengths = []
for i in range(len(Data_Sets1)):
lengths.append(len(Data_Sets1[i]))
index = lengths.index(max(lengths))
Chan1 = Data_Sets1[index]
Chan2 = Data_Sets2[index]
Start_Header = Headers[index]
if (len(Chan1) == 0 | len(Chan2) == 0):
continue
try:
Date = Start_Header[index][0]
Time = Start_Header[index][1]
except IndexError:
logging.critical("file " + fileName + " is unusuable")
continue
"""
Clostest_Power = int(np.log(len(Chan1))/np.log(2))
Length = 2 ** Clostest_Power
logging.debug("Length of the file is " + str(Length))
Chan1 = Chan1[0:Length]
Chan2 = Chan2[0:Length]
"""
logging.debug("Length of channels is " + str(len(Chan1)))
window = np.hanning(Window_Width)
t= s.Time_Array(len(Chan1),Sample_Rate)
window2 = np.hanning(len(Chan1))
Noise_Frequincies = []
for i in range(1,125):
Noise_Frequincies.append(60.0*float(i))
Noise_Frequincies.append(180.0)
filter1 = s.Noise_Reduction(Sample_Rate,Noise_Frequincies,Chan1)
filter2 = s.Noise_Reduction(Sample_Rate,Noise_Frequincies,Chan2)
logging.info("Starting the plots")
fig1, (ax1, ax2) = plt.subplots(nrows=2)
spec1, freqs1, time1 = mlab.specgram(filter1, NFFT=Window_Width, Fs=Sample_Rate, window=window, noverlap=Over_Lap)
im1 = ax1.imshow(spec1, cmap=cm.get_cmap("rainbow"), norm=colors.LogNorm(), origin='lower',
extent=[t[0], t[len(t)-1], freqs1.min(), 8000],aspect='auto',vmin=1e-5,vmax=1e5)
ax1.set_title(str(Date) + "-" + str(Time) + " Channel 1")
ax1.set_ylabel("Freqency Hz")
spec2, freqs2, time2 = mlab.specgram(filter2, NFFT=Window_Width, Fs=Sample_Rate, window=window, noverlap=Over_Lap)
im2 = ax2.imshow(spec2, cmap=cm.get_cmap("rainbow"), norm=colors.LogNorm(), origin='lower',
extent=[t[0], t[len(t)-1], freqs2.min(), 8000],aspect='auto',vmin=1e-5,vmax=1e5)
cax1, kw1 = matplotlib.colorbar.make_axes(ax1)
colorbar(im1,cax=cax1,**kw1)
cax2, kw2 = matplotlib.colorbar.make_axes(ax2)
colorbar(im2,cax=cax2,**kw2)
ax2.set_title(str(Date) + "-" + str(Time) + " Channel 2")
ax2.set_ylabel("Freqency Hz")
save1 = save_path+pathpart + changedir+specgram_path
if not os.path.exists(save1):
os.makedirs(save1)
savefig(os.path.join(save1,str(Date) + "-" + str(Time) + "-Power_Spec1.png"))
logging.info("Spectrogram path is " + save1)
fig2, (ax4,ax6) = plt.subplots(nrows=2)
final_fft = []
fft = s.Full_FFT(filter1,window2)
for i in range(0,len(fft)):
final_fft.append(np.absolute(fft[i]))
freqs = []
for i in range(0,len(final_fft)):
freqs.append(i*Sample_Rate/float(len(final_fft)))
ax4.plot(freqs, final_fft)
new_fft = []
new = s.Full_FFT(filter2,window2)
for i in range(0,len(new)):
new_fft.append(np.absolute(new[i]))
ax6.plot(freqs,new_fft)
save2 = save_path+pathpart+ changedir + freq_path
logging.info("Frequency path is " + save2