Небольшое вступление

Коллеги, добрый день! В моей карьере часто встречались кейсы, когда бизнес хотел видеть определенные данные, для статистики или отчётов. И часто бывало что кто-то из команды выгружал, оформлял и отправлял по почте эту выгрузку в ручную на постоянной основе или за период.

И то, что мы можем автоматизировать, мы автоматизируем, правда? =)

Что нужно сделать

Для коллег я подготовил шаблон, чтобы не тратить много времени если в задаче необходим такой скрипт.

И всё что требуется, это подставить свои креды и свой запрос. Ну и учесть некоторые моменты при работе, описание под шаблоном =)

Предлагаю использовать его как основу, ну и если нужно будет его подкорректировать, то вам это никто не запрещает.

import cx_Oracle
import csv
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
 
 
# Подключение к базе данных Oracle
dsn_tns = cx_Oracle.makedsn('hostname', 'port', service_name='service_name')
connection = cx_Oracle.connect(user='username', password='password', dsn=dsn_tns)
cursor = connection.cursor()
 
# Выполнение запроса
cursor.execute("SELECT * FROM table")
result = cursor.fetchall()
 
# Запись результата в CSV файл
with open('output.csv', 'w', newline='') as csvfile:
    csv_writer = csv.writer(csvfile)
    csv_writer.writerows(result)
 
# Отправка файла по почте
msg = MIMEMultipart()
msg['From'] = 'sender@example.com'
msg['To'] = 'receiver@example.com'
msg['Subject'] = 'Результат запроса из базы данных Oracle'
 
filename = 'output.csv'
attachment = open(filename, 'rb')
 
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', f'attachment; filename= {filename}')
 
msg.attach(part)
 
server = smtplib.SMTP('smtp.example.com', 25)
server.starttls()
server.send_message(msg)
server.quit()
 
# Закрытие соединения с базой данных
cursor.close()
connection.close()

Шаблон для оракла, если нам нужна постгря, то заменяем библиотеку import cx_Oracle и подключение к БД на:

import psycopg2 


connection = psycopg2.connect(dbname=cred.dbname, user=cred.dbuser, host=cred.dbhost,
                                  password=cred.dbpass)
cursor = connection.cursor()
select(connection,cursor)

Для того чтобы скрипт работал с ораклом, нужны еще некоторые манипуляции:

  1. Скачиваем instantclient https://download.oracle.com/otn_software/nt/instantclient/216000/instantclient-basic-windows.x64-21.6.0.0.0dbru.zip

  2. Файлы библиотек переносим в каталог с Python

    • oci.dll

    • ocijdbc21.dll

    • ociw32.dll

    • oramysql.dll

    • orannzsbb.dll

    • oraocci21.dll

    • oraocci21d.dll

    • oraociei.dll

    • orasql.dll

Некоторые комментарии по скрипту:

  • Имя почтового ящика:

    msg['From'] = 'sender@example.com'

    Тут мы указываем имя нужного почтового ящика, он может быть любым, так как msg отправляется на сервер анонимно server = smtplib.SMTP('smtp.example.com', 25)

  • Для того чтобы скрипт работал в автоматическом режиме, то есть 2 варианта. Можно упаковать скрипт в докер и запускать его по крону, либо использовать библиотеку schedule и запускать по условному крону на своей машине

    Как у меня работает schedule:

    import schedule

    schedule.every().day.at("09:00").do(connect)

    while True:
    schedule.run_pending()
    time.sleep(1)

    В do(connect) мы ссылаемся на первую функцию в списке

    В моём рабочем скрипте это выглядит так
    В моём рабочем скрипте это выглядит так

Заключение

Это моя первая статья на хабре, поэтому буду очень рад фидбеку и если она кому то поможет в работе =)

Пока - пока :-)