Reputation: 160
I'm using python 3.6 to generate files. Then, I need to send these files through automated mails. Here's a bit of code :
myFiles = []
myFiles.append(getFirstFile()) # creates a file and returns its path
# its name is '2019-06-24_15-01-57_hist'
myFiles.append(getSecondFile()) # creates another file and returns its path
# myFiles is a list of strings
sendAutoMail(myFiles) # sends an automatic mail with the files attached
All these functions work fine when not implemented in the same script. But now that I put all these together here's the error I get from the sendAutoMail()
function :
FileNotFoundError: [Errno 2] No such file or directory: '2019-06-24_15-01-57_hist'
When I look in the directory, the files are created indeed.
Creating files with getFirstFile()
and getSecondFile()
, and then run sendAutoMail([File1, File2])
in two steps seems to work fine. However it won't work in one unique script.
Any idea ?
EDIT : okay here are the functions, not sure this will help
def getFirstFile(mean, variance): # prend en paramètres une moyenne et une variance
import matplotlib.pyplot as plt
import numpy as np
import scipy.stats as stats
import math
mu = mean
sigma = math.sqrt(variance)
x = np.linspace(mu - 3*sigma, mu + 3*sigma, 100)
plt.grid(True)
plt.plot(x, stats.norm.pdf(x, mu, sigma)) #création d'une courbe normale centrée en mu et d'écart type sigma
# plt.show()
filename = dateFileName()+"_firstFunction"
plt.savefig(filename)
def dateFileName():
import datetime
ladate = str(datetime.datetime.now()) # récupération de la date et formattage
ladate = ladate.split(sep=".")
ladate = ladate[0].replace(" ","_")
ladate = ladate.replace(":","-")
return ladate
I am using the date as a file name because I don't know any other alternative to ensure the filename is unique.
Upvotes: 0
Views: 91
Reputation: 1525
Digging into the source code of matplotlib
I found that calling plt.savefig(filename)
using a path (the name alone is a relative path) will then call the function Figure.print_[format](filename, ...)
with format being the save format like PDF, PNG, TIFF.... The default is PNG.
Figure.print_png
uses Pillow to write the image, specifically Pillow.Image.save
. That function opens the file, writes to it and closes the file.
The problem is, it closes the file directly and only that. When closing a file directly, python uses the default system buffer and flushing cycle, so when a file is closed directly, it is not immediately written to disk, or at least not completely (depending on the size a portion of it might have been saved).
To prevent that from happening, open the file on your code inside a with
statement, which flush and close the file when exiting like this:
def getFirstFile(mean, variance): # prend en paramètres une moyenne et une variance
import matplotlib.pyplot as plt
import numpy as np
import scipy.stats as stats
import math
mu = mean
sigma = math.sqrt(variance)
x = np.linspace(mu - 3*sigma, mu + 3*sigma, 100)
plt.grid(True)
plt.plot(x, stats.norm.pdf(x, mu, sigma)) #création d'une courbe normale centrée en mu et d'écart type sigma
# plt.show()
filename = dateFileName()+"_firstFunction"
with open(filename, 'r+b') as fl:
plt.savefig(fl)
return filename
That should solve your problem, on some edge cases it might be that the last buffered portion will still have not been save. In this case you can force writing the buffer to disk with os.fsync(fl)
right before the return filename
statement.
Upvotes: 1