I'm doing some multiprocessing, and I'd like to understand why the following piece of code sometimes (but never at the first iteration of the loop) generates the following error :
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x7f6c40d25ba8>>
Traceback (most recent call last):
File "/usr/lib/python3.5/tkinter/__init__.py", line 3359, in __del__
self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Tcl_AsyncDelete: async handler deleted by the wrong thread
Traceback (most recent call last):
File "Analize0.py", line 94, in <module>
Lambda = np.array(Rescal.multiprocess_loop_grouped(grouped_spatial_lambda, range(Nalti), Group_size, N_thread, *args))
File "/home/gadal/PythonLib_perso/Rescal/Lib_Rescal.py", line 135, in multiprocess_loop_grouped
return [dic[i] for i in sorted(dic.keys())]
File "/home/gadal/PythonLib_perso/Rescal/Lib_Rescal.py", line 135, in <listcomp>
return [dic[i] for i in sorted(dic.keys())]
File "<string>", line 2, in __getitem__
File "/usr/lib/python3.5/multiprocessing/managers.py", line 717, in _callmethod
kind, result = conn.recv()
File "/usr/lib/python3.5/multiprocessing/connection.py", line 250, in recv
buf = self._recv_bytes()
File "/usr/lib/python3.5/multiprocessing/connection.py", line 407, in _recv_bytes
buf = self._recv(4)
File "/usr/lib/python3.5/multiprocessing/connection.py", line 383, in _recv
raise EOFError
EOFError
Here is the code :
list_per = sorted(glob.glob('Plage*'))
Nper = len(list_per)
for simul_per in list_per :
print(simul_per)
path_small = os.getcwd()
os.chdir(simul_per)
list_alti = sorted(glob.glob('ALTI00*'))
Nalti = len(list_alti)
Group_size = Nalti // N_thread
print('Reading files ...')
Map = np.array(Rescal.multiprocess_loop_grouped(Rescal.read_file, list_alti, Group_size, N_thread))
print('Processing data ...')
##################################################################################### Data analysis
Y_simul = (100, 500)
Deviation = np.empty((Nalti,Y_simul[1] - Y_simul[0], Map.shape[-1]))
for i in range(Nalti): ############### removing average beach topography
Deviation[i,:,:] = Map[i,Y_simul[0]:Y_simul[1],:] - np.mean(Map[i,Y_simul[0]:Y_simul[1],:], axis = 0, keepdims = True)
############ Beach wavelength
print(' Beach wavelength ...')
X_beach = (300,650)
args = [X_beach, Deviation]
Temp = Rescal.multiprocess_loop_grouped(find_lambda_plage, range(Nalti), Group_size, N_thread, *args)
Lambda_plage = np.array([i[0] for i in Temp])
Orientation = np.array([i[1] for i in Temp])
############ Wavelength as a function of space
print(' Wavelength as a function of space ...')
args = [Deviation]
Lambda = np.array(Rescal.multiprocess_loop_grouped(grouped_spatial_lambda, range(Nalti), Group_size, N_thread, *args))
print('Saving data ...')
Data = {}
Data['Lambda_finger'] = Lambda_finger
Data['Lambda_plage'] = Lambda_plage
Data['Orientation'] = Orientation
Data['Map'] = Map
Data['Lambda'] = Lambda
np.save('Data', Data)
print('Saving figures ...')
plt.figure()
plt.plot(Lambda_finger)
plt.ylim([0, 300])
plt.savefig('Lambda_finger.pdf')
plt.clf()
plt.plot(Lambda_plage)
plt.plot(Lambda_finger[:,10])
plt.ylim([0, 300])
plt.legend(('Lambda plage', 'Lambda finger'))
plt.savefig('Lambda.pdf')
plt.clf()
plt.imshow(Lambda)
cbar = plt.colorbar()
plt.xlabel('x')
plt.ylabel('Time')
cbar.set_label('Lambda')
plt.clim([0, 80])
plt.savefig('Spatial_time_lambda.pdf')
plt.close('all')
os.chdir(path_small)
I'm multiprocessing some independent tasks over the files I have using a function I've written, and which is described here : Function that multiprocesses another function.
However, the functions called by the the one that multiprocesses them never call matplotlib, which is called by the main thread after that the last multiprocessing call is done.
For example, the function in the previous error grouped_spatial_lambda
is made of :
def spatial_evolution_lambda(Map):
Lambda = []
for x in range(Map.shape[1]):
Lambda.append(Anls.find_first_max(autocorr(Map[:,x])))
return Lambda
def grouped_spatial_lambda(indexes,dic,Deviation):
for i in indexes:
dic[i] = spatial_evolution_lambda(Deviation[i,:,:])
def find_first_max(a, valmax = False):
inds = find_peaks(a)[0]
if len(inds) > 0:
l = inds[inds > 5]
if len(l) > 0:
testerr = 0
a_norm = a/np.max(a)
x_fit = np.array([i for i in range(int(l[0]/2), int(3*l[0]/2))])
x_fit = x_fit[x_fit < len(a)]
y_fit = a_norm[x_fit]
x_fit = x_fit[y_fit > 0]
y_fit = a_norm[x_fit]
if x_fit.size == 0 or len(x_fit) < 3 :
lamb = np.nan
amp = np.nan
else:
try:
# popt, pcov = curve_fit(gaus,x_fit.ravel(),y_fit.ravel(), p0=[np.max(y_fit),np.mean(x_fit),np.mean(x_fit)])
popt, pcov = curve_fit(gaus,x_fit,y_fit, p0=[np.max(y_fit),np.mean(x_fit),np.mean(x_fit)])
except RuntimeError:
lamb = np.nan
amp = np.nan
testerr = 1
if testerr == 0:
lamb = popt[1]
amp = popt[0]
else:
lamb = np.nan
amp = np.nan
else:
lamb = np.nan
amp = np.nan
if valmax == False:
return lamb
else:
return lamb, amp, 1.96/np.sqrt(a.size)
From what I understand from the posted error, tkinter generates an exception that leads to EOF error ? How can this be as the call to matplotlib is done after the multiprocessing of the other functions ? Does it have something to do with the loop ? (Previous call to matplotlib .. ?) How do I force matplotlib to run in the main thread ?