Python Email Notification Scripts for Model Training, Data Processing, and Financial Modeling
This article explains how to use Python scripts with the email and smtplib libraries to automatically send progress updates and completion notifications for long‑running tasks such as model training, data transfer, and financial simulations, including code examples for MIME construction and SMTP delivery.
The author frequently writes Python scripts for data handling, model training, and related tasks, and proposes sending automated email notifications to stay productive while waiting for long‑running processes.
What is needed – Depending on the task (model training, data processing/transfer, or financial modeling), specific information such as loss curves, runtime, model name, or sample results should be included in the notification.
Model training notifications – Update every n epochs with key metrics (loss, accuracy), visualizations, model directory, runtime, and sample outputs. Example code:
import notify
START = datetime.now() # before training begins
MODELNAME = "SynthwaveGAN"
NOTIFY = 100 # send update every 100 epochs
if e % notify_epoch == 0 and e != 0:
txt = f"{MODELNAME} update as of {datetime.now().strftime('%H:%M:%S')}."
msg = notify.message(
subject="Synthwave GAN",
text=txt,
img=[
f"../visuals/{MODELNAME}/epoch_{e}_loss.png",
f"../visuals/{MODELNAME}/epoch_{e}_iter_{i}.png"
]
)
notify.send(msg)Every 100 epochs an email containing the above information is sent.
Data processing and transfer – Often the most time‑consuming step. Example using a Python script to bulk‑upload files to SQL Server and send a completion email:
import os
import notify
from data import Sql
dt = Sql(database123, server001) # connect to SQL Server
for i, file in enumerate(os.listdir("../data/new")):
dt.push_raw(f"../data/new/{file}") # upload file
msg = notify.message(
subject="SQL Data Upload",
text=f"Data upload complete, {i} files uploaded."
)
notify.send(msg)A try‑except block can capture upload errors and include them in the final notification.
Financial model notifications – Although fast, large‑scale simulations may still benefit from summaries. Example code sends runtime, processed loan count, and visualizations:
end = datetime.datetime.now() # ending time
hours, rem = divmod((end - start).seconds, 3600)
mins, secs = divmod(rem, 60)
runtime = f"{hours:02d}:{mins:02d}:{secs:02d}"
notify.msg(
subject="Cashflow Model Completion",
text=f"{len(model.output)} loans processed. Total runtime:{runtime}",
img=[
"../vis/loan01_amortisation.png",
"../vis/loan07_amortisation.png",
"../vis/loan01_profit_and_loss.png",
"../vis/loan07_profit_and_loss.png"
]
)
notify.send(msg)MIME construction – The script uses the email package to build a MIMEMultipart message with MIMEText , MIMEImage , and MIMEApplication parts. The function below creates the message object:
import os
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
def message(subject="PythonNotification", text="", img=None, attachment=None):
msg = MIMEMultipart()
msg["Subject"] = subject
msg.attach(MIMEText(text))
if img is not None:
if type(img) is not list:
img = [img]
for one_img in img:
img_data = open(one_img, "rb").read()
msg.attach(MIMEImage(img_data, name=os.path.basename(one_img)))
if attachment is not None:
if type(attachment) is not list:
attachment = [attachment]
for one_attachment in attachment:
with open(one_attachment, "rb") as f:
file = MIMEApplication(f.read(), name=os.path.basename(one_attachment))
file["Content-Disposition"] = f'attachment; filename="{os.path.basename(one_attachment)}"'
msg.attach(file)
return msgSMTP sending – After constructing the message, smtplib handles delivery. The following function logs into Outlook’s SMTP server, sends the email, and gracefully handles network errors:
import smtplib
import socket
def send(server="smtp-mail.outlook.com", port=587, msg=None):
try:
smtp = smtplib.SMTP(server, port)
smtp.ehlo()
smtp.starttls()
with open("../data/email.txt", "r") as fp:
email = fp.read()
with open("../data/password.txt", "r") as fp:
pwd = fp.read()
smtp.login(email, pwd)
smtp.sendmail(email, email, msg.as_string())
smtp.quit()
except socket.gaierror:
print("Network connection error, email not sent.")Finally, the two parts are combined to build and send a notification:
# build a message object
msg = message(text="See attached!", img="important.png", attachment="data.csv")
send(msg) # defaults to OutlookThe complete workflow enables automated email updates for any lengthy Python‑driven process, improving productivity and providing clear status reports.
Python Programming Learning Circle
A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.