What can I improve about this code in order to be production-ready? I'm not worried about security but about errors that could occur.
What exceptions should I catch? I feel overwhelmed about exceptions because I feel that there are a lot of exceptions that one can consider.
What else should I do? Should I do unit testing for this?
The script first loads the client list from an SQL database, then takes the daily work quantity about pallet movements from a SQL database, after that it writes a .csv file with this data, and finally sends it through email.
import pyodbc
import csv
import smtplib
import os.path
from datetime import date, timedelta
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
def load_clients():
client_list = {}
connection_string = f'*'
query = """
SELECT clifor.a1_codice_clifor, anacf.ragione_soc_fiscale
FROM anacf anacf, clifor clifor
WHERE (clifor.a1_ditta_codice=5)
AND (clifor.a1_tipo_cli1_for2=1)
AND
(anacf.a1_codice_anagrafica_generale=clifor.a2_anagrafica_codice)
"""
cnxn = pyodbc.connect(connection_string, autocommit=True)
with cnxn:
cursor = cnxn.cursor()
cursor.execute(query)
while True:
row = cursor.fetchone()
if not row:
break
client_list[row[0]] = row[1]
return client_list
def load_movements(clients):
movement_list = []
connection_string = f'*'
query = """
SELECT datadoc, cliente,
SUM (@DECODE(tipodoc, 3 ,palletts)) AS inputs,
SUM (@DECODE(tipodoc, 5 ,palletts)) AS outputs
FROM docmagat
WHERE ditta=5
AND anno=2020
AND tipodoc in (3,5)
AND datadoc=SYSDATE-1
GROUP BY 1,2
"""
cnxn = pyodbc.connect(connection_string)
with cnxn:
cursor = cnxn.cursor()
cursor.execute(query)
while True:
row = cursor.fetchone()
if not row:
break
inputs = 0 if row[2] is None else row[2]
outputs = 0 if row[3] is None else row[3]
movement_list.append(tuple(
(clients[row[1]], inputs, outputs, inputs
+ outputs)))
return movement_list
def load_file(movements, yesterday, folder):
filename = 'pallet_movements ' + yesterday + '.csv'
full_path = os.path.join(folder, filename)
with open(full_path, mode='w', newline='') as pallet_movements:
movements_writer = csv.writer(pallet_movements,
delimiter=';')
movements_writer.writerow(['Day: ' + yesterday])
movements_writer.writerow(['Company', 'inputs', 'outputs',
'Total'])
for movement in movements:
movements_writer.writerow(movement)
return filename
def send_email(filename, yesterday, folder):
sender = "*"
destination = "*"
msg = MIMEMultipart()
msg['Subject'] = 'Pallet movements ' + yesterday
msg['From'] = sender
msg['To'] = destination
message_text = 'Good morning,\n\nYou can find Pallet movements from\
day ' + yesterday + ' attached.\n\nGoodbye'
msg.attach(MIMEText(message_text))
full_path = os.path.join(folder, filename)
attachment = MIMEApplication(open(full_path, 'rb').read())
attachment.add_header('Content-Disposition', 'attachment',
filename=filename)
msg.attach(attachment)
try:
with smtplib.SMTP('*', 587) as smtpObj:
smtpObj.ehlo()
smtpObj.starttls()
smtpObj.login("*", "*")
smtpObj.sendmail(sender, destination, msg.as_string())
except Exception as e:
print(e)
def main():
yesterday = date.today() - timedelta(days=1)
yesterday = yesterday.strftime(f'%d-%m-%Y')
local_folder = os.path.dirname(os.path.abspath(__file__))
clients = load_clients()
movements = load_movements(clients)
filename = load_file(movements, yesterday, local_folder)
send_email(filename, yesterday, local_folder)
if __name__ == "__main__":
main()
with smtplib.SMTP('*, 587) as smtpObj:looks like it's missing an'. \$\endgroup\$foowe will send you an email, throughbar, that looks like …. Upon sending the email we add the user to the database throughbazthat adds to the tableUserTablethat has the following columns …." \$\endgroup\$