Geben Sie den Bericht mit Python aus DB in PDF aus, hängen Sie ihn automatisch an eine E-Mail an und senden Sie ihn

Part-san überprüft täglich den Betriebsstatus von Kommunikationsgeräten auf einem speziellen Bildschirm, erstellt einen Bericht und sendet ihn per E-Mail. Ich denke, dass es für jedes Unternehmen durchaus üblich ist, ähnliche Arbeiten auszuführen, aber aus Sicht eines Ingenieurs ist eine solche Routine unmöglich, deshalb habe ich ein kleines Tool geschrieben.

Denkweise

Wir wissen, dass sich alle zugrunde liegenden Informationen in der Datenbank befinden. Daher sollte ** ein Programm, das eine aus der Datenbank generierte PDF-Datei an eine E-Mail anhängt und diese sendet **, auf der Serverseite implementiert und auch in cron registriert werden.

Ausführungsumgebung

So generieren Sie ein Formular

Ich dachte darüber nach, mit Pythons ** OpenPyXL ** -Modul in eine Excel-Datei auszugeben. [Erstellen Sie ein PDF im Lebenslaufformat mit Python + Reportlab] Inspiriert von diesem Artikel habe ich beschlossen, eine PDF-Datei mit dem Modul ** ReportLab ** auszugeben.

Installation


pip3 install reportlab

Formularmuster

report.png

Codebeispiel

Es gibt verschiedene Möglichkeiten, eine Verbindung von Python zu MySQL herzustellen, aber ich hatte zufällig ** MySQLdb ** auf dem Server, also habe ich es verwendet. Ich werde es ohne große Änderungen veröffentlichen, aber ich denke, das Schema ist einigermaßen vielseitig, also beziehen Sie sich bitte darauf.

Python


"""
Generieren Sie einen Bericht im PDF-Format aus der Datenbank, hängen Sie ihn an eine E-Mail an und senden Sie ihn
"""
__author__  = "MindWood"
__version__ = "1.00"
__date__    = "31 Oct 2019"

import MySQLdb
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.cidfonts import UnicodeCIDFont
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4, portrait
from reportlab.lib.units import mm
from reportlab.platypus import Table, TableStyle
import smtplib
from email import encoders
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
import os
import datetime

def setup_page():
    """Registrieren Sie die Schriftart und legen Sie die Kopf- und Fußzeile fest"""
    pdfmetrics.registerFont(UnicodeCIDFont(font_name))  #Schriftregistrierung
    #Kopfzeilenzeichnung
    c.setFont(font_name, 18)
    c.drawString(10*mm, height - 15*mm, "Betriebsstatusbericht der Kommunikationsausrüstung")
    c.setFont(font_name, 9)
    c.drawString(width - 58*mm, height - 10*mm, header_date)
    #Fußzeilenzeichnung
    c.drawString(10*mm, 16*mm, "Die Terminal-IDs, die innerhalb der letzten 8 Stunden Daten empfangen haben, werden grün angezeigt.")
    global page_count
    c.drawString(width - 15*mm, 5*mm, "{}Seite".format(page_count))  #Seitenzahl zeichnen
    page_count += 1

def control_break():
    """Kontrollpause nach Kundenname"""
    if ctrl_break_key == "": return
    c.showPage()
    setup_page()

def page_break(n):
    """Seitenumbruchverarbeitung"""
    n += 1
    if n < 28: return n
    c.showPage()
    setup_page()
    return 0

#Einstellen des Basisdatums und der Basiszeit
dt = datetime.datetime.now()
header_date = "{:%Y Jahr%-m Monat%-d Tag%-Uhr%-M Minuten jetzt}".format(dt)
safe_date = "{:%Y/%m/%d %H:%M}".format(dt + datetime.timedelta(hours=-8))  #vor 8 Stunden

#Initialisierung der PDF-Datei
pdf_filename = "report{:%y%m}.pdf".format(dt)
c = canvas.Canvas(pdf_filename, pagesize=portrait(A4))  #PDF-Dateiname und Papiergröße
width, height = A4  #Holen Sie sich Papiergröße
c.setAuthor("MindWood")
c.setTitle("IoT gateway Working report")
c.setSubject("")

font_name = "HeiseiKakuGo-W5"  #Schriftartenname
page_count = customer_no = 1
setup_page()
ctrl_break_key = ""

#Stellen Sie eine Verbindung zu MySQL her
conn = MySQLdb.connect(host="localhost", user="xxxxxx", passwd="yyyyyy", db="zzzzzz", charset="utf8")
cursor = conn.cursor(MySQLdb.cursors.DictCursor)

#Erfassung von Stamminformationen von Kommunikationsgeräten
cursor.execute('''
SELECT c.Name as CustName, d.Name as DeptName, a.Code, a.Area, hex(a.MacAddress) as MacAddress
FROM table0001 a
LEFT JOIN table0002 c ON a.CustomerID = c.CustomerID
LEFT JOIN table0003 d ON a.CustomerID = d.CustomerID AND a.DeptID = d.DeptID
ORDER BY c.CustomerID, d.DeptID, MacAddress;
''')

gws = cursor.fetchall()
for row_gw in gws:
    #Seitenumbruch, wenn sich der Kundenname ändert
    if ctrl_break_key != row_gw["CustName"]:
        control_break()
        ctrl_break_key = row_gw["CustName"]
        c.setFont(font_name, 15)
        c.drawString(10*mm, height - 36*mm, "{}. {}".format(customer_no, ctrl_break_key))
        customer_no += 1

        data = [ [ "Abteilungsname", "Verwaltungscode", "Installationsbereich", "MAC-Adresse" ] ]  #Überschrift des Kommunikationsgeräts
        table = Table(data, colWidths=(70*mm, 40*mm, 40*mm, 40*mm), rowHeights=8*mm)  #Eine Tabelle erstellen
        table.setStyle(TableStyle([
            ("FONT", (0, 0), (-1, -1), font_name, 11),            #Schriftart
            ("BOX", (0, 0), (-1, -1), 1, colors.black),           #Außengrenze
            ("INNERGRID", (0, 0), (-1, -1), 0.25, colors.black),  #Innenrand
            ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),               #Richten Sie die Zeichen vertikal in der Mitte aus
            ("BACKGROUND", (0, 0), (-1, -1), colors.lightgrey),   #Mit Grau füllen
        ]))
        table.wrapOn(c, 10*mm, height - 50*mm)  #Tischposition
        table.drawOn(c, 10*mm, height - 50*mm)  #Tischposition
        line_count = 1

    styles = [
        ("FONT", (0, 0), (-1, -1), font_name, 11),
        ("BOX", (0, 0), (-1, -1), 1, colors.black),
        ("INNERGRID", (0, 0), (-1, -1), 0.25, colors.black),
        ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
    ]
    MacAddress = row_gw["MacAddress"]
    if os.uname()[1] == "ip-172-35-10-XX":  #Für einen bestimmten Server
        MacAddress = "XXXXXXXXXXXX"
        styles.append(("BACKGROUND", (3, 0), (3, 0), colors.yellow))  #Mit Gelb füllen

    data = [ [ row_gw["DeptName"], row_gw["Code"], row_gw["Area"], MacAddress ] ]  #Detaillierte Daten der Kommunikationsausrüstung
    table = Table(data, colWidths=(70*mm, 40*mm, 40*mm, 40*mm), rowHeights=8*mm)
    table.setStyle(TableStyle(styles))
    table.wrapOn(c, 10*mm, height - 50*mm - 8*mm * line_count)
    table.drawOn(c, 10*mm, height - 50*mm - 8*mm * line_count)
    line_count = page_break(line_count)

    #Erfassung von Datum und Uhrzeit des Datenempfangs
    cursor.execute('''
    SELECT hex(TermID) as TermID, from_unixtime(min(Time),"%Y/%m/%d %H:%i:%S") as from_date, from_unixtime(max(Time),"%Y/%m/%d %H:%i:%S") as to_date FROM table0005
    WHERE MacAddress=0x{} GROUP BY TermID ORDER BY to_date;
    '''.format(MacAddress))

    terms = cursor.fetchall()
    for row_term in terms:
        data = [ [ "Zeitraum", row_term["from_date"] + " ~ " + row_term["to_date"], "Terminal ID", row_term["TermID"] ] ]  #Detaillierte Daten des Terminals
        table = Table(data, colWidths=(25*mm, 100*mm, 25*mm, 40*mm), rowHeights=8*mm)
        styles = [
            ("FONT", (0, 0), (-1, -1), font_name, 11),
            ("BOX", (0, 0), (-1, -1), 1, colors.black),
            ("INNERGRID", (0, 0), (-1, -1), 0.25, colors.black),
            ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
            ("BACKGROUND", (0, 0), (0, 0), colors.lightgrey),
            ("BACKGROUND", (2, 0), (2, 0), colors.lightgrey),
        ]
        if row_term["to_date"] > safe_date:  #Wenn das Datum und die Uhrzeit des letzten Empfangs innerhalb der letzten 8 Stunden liegen
            styles.append(("BACKGROUND", (3, 0), (3, 0), colors.palegreen))
        table.setStyle(TableStyle(styles))
        table.wrapOn(c, 10*mm, height - 50*mm - 8*mm*line_count)
        table.drawOn(c, 10*mm, height - 50*mm - 8*mm*line_count)
        line_count = page_break(line_count)

#Trennen Sie MySQL
cursor.close()
conn.close()

#In PDF-Datei speichern
c.showPage()
c.save()

#PDF-Datei per E-Mail senden
from_addr = "[email protected]"
to_addr   = "[email protected]"
bcc_addr  = "[email protected]"  #Mehrere Angaben können durch Kommas getrennt angegeben werden
rcpt = bcc_addr.split(",") + [to_addr]

msg = MIMEMultipart()
msg["Subject"] = "Betriebsstatusbericht der Kommunikationsausrüstung{:%Y Jahr%-m Monat}".format(dt)
msg["From"] = from_addr
msg["To"] = to_addr

msg.attach(MIMEText("""
Diese E-Mail wird automatisch vom System gesendet.
Der Systembetriebsstatus des XXXX-Servers ist angehängt.
""".strip()))

attachment = MIMEBase("application", "pdf")
file = open(pdf_filename, "rb+")
attachment.set_payload(file.read())
file.close()
encoders.encode_base64(attachment)
attachment.add_header("Content-Disposition", "attachment", filename=pdf_filename)
msg.attach(attachment)

smtp = smtplib.SMTP("smtp.xxxxxx.com", 587)  #SMTP-Server
smtp.starttls()
smtp.login(from_addr, "PASSWORD")  #Passwort
smtp.sendmail(from_addr, rcpt, msg.as_string())
smtp.close()

Recommended Posts

Geben Sie den Bericht mit Python aus DB in PDF aus, hängen Sie ihn automatisch an eine E-Mail an und senden Sie ihn
So senden Sie automatisch E-Mails mit Anhängen mithilfe der Google Mail-API in Python
Ich habe versucht, das automatische Senden einer E-Mail durch Doppelklicken auf das Symbol [Python] zu ermöglichen
[Python] Senden Sie das von der Webkamera aufgenommene Bild an den Server und speichern Sie es
Senden Sie eine E-Mail mit Python an Spushis Adresse
Ich habe versucht, das automatische Senden einer E-Mail durch Doppelklicken auf das Symbol [GAS / Python] zu ermöglichen
Extrahieren Sie Bilder und Tabellen mit Python aus PDF, um die Berichtslast zu verringern
Es ist einfach, SQL mit Python auszuführen und das Ergebnis in Excel auszugeben
[Python] Senden Sie eine E-Mail aus Google Mail mit einer zweistufigen Authentifizierungseinstellung
Vorsichtsmaßnahmen bei der Eingabe von CSV mit Python und der Ausgabe an json, um exe zu erstellen
[Python] Mail mit Outlook senden
HTML-Mail mit Bild zum Senden mit Python
Senden Sie eine E-Mail mit Amazon SES + Python
Was tun, wenn Sie mit Python keine E-Mail an Yahoo senden konnten?
Senden Sie E-Mails mit Python an eine bestimmte E-Mail-Adresse, ohne SMTP festzulegen
Extrahieren Sie das Ergebnis des TOP-Befehls mit USER und geben Sie es als CSV aus
Senden und Empfangen von Bilddaten als JSON in Python über das Netzwerk
[Outlook] Ich habe versucht, mit Python automatisch eine tägliche Berichtsmail zu erstellen
Lesen Sie die CSV-Datei mit Python und konvertieren Sie sie unverändert in DataFrame
Ich habe GhostScript mit Python ausgeführt, das PDF in Seiten aufgeteilt und es in ein JPEG-Bild konvertiert.
Die Geschichte, ein Tool zum Laden von Bildern mit Python zu erstellen ⇒ Speichern unter
Lesen Sie die Daten des NFC-Lesegeräts, das mit Python an Raspberry Pi 3 angeschlossen ist, und senden Sie sie mit OSC an openFrameworks
So geben Sie eine Zeichenfolge in Python ein und geben sie unverändert oder in die entgegengesetzte Richtung aus.
Senden Sie eine E-Mail vom VirtualBox CentOS8-Server mit Ihrem Google-Konto als Sendeadresse und dem App-Passwort
Lesen Sie JSON mit Python und geben Sie CSV aus
[Python] Kombinieren von Listen mit Zahlen zu Zeichenfolgen und Schreiben in eine Ausgabedatei
Senden Sie eine E-Mail mit Excel in Python
Ich habe versucht, die Literatur des neuen Corona-Virus mit Python automatisch an LINE zu senden
Ich habe es geschafft, weil der Brauch, eine Zip mit einem Passwort an eine E-Mail anzuhängen und "Ich werde Ihnen das Passwort separat senden" zu sagen, mühsam ist.
Wenn Sie Probleme beim Senden von E-Mails mit Python smtplib haben, rufen Sie die Befehlszeile auf
Übergeben Sie ein Array von PHP an PYTHON und führen Sie eine Numpy-Verarbeitung durch, um das Ergebnis zu erhalten
Prozedur zum Laden von MNIST mit Python und zur Ausgabe an png
Probieren Sie die DB-Operation mit Python aus und visualisieren Sie sie mit d3
Konvertieren Sie das Bild in .zip mit Python in PDF
Erhalten Sie E-Mails von Google Mail und beschriften Sie sie mit Python3
Lesen Sie die json-Datei mit Python, formatieren Sie sie und geben Sie json aus
Geben Sie MinGW als den in Python verwendeten Compiler an
Mail per Python senden
Ich möchte mit Python nur das Gesicht aus einem Personenbild ausschneiden und speichern ~ Gesichtserkennung und Zuschneiden mit face_recognition ~
Rufen Sie die Excel-Liste rekursiv in einem bestimmten Ordner mit Python ab und schreiben Sie sie in Excel.
Ich habe einen Server mit Python-Socket und SSL erstellt und versucht, über den Browser darauf zuzugreifen
Geben Sie die Bilddaten mit Flask of Python zurück und zeichnen Sie sie in das Canvas-Element von HTML
Ich möchte ein englisches Papier aus dem PDF-Format kopieren und in die Google-Übersetzung einfügen
[Python / Ruby] Mit Code verstehen Wie man Daten aus dem Internet abruft und in CSV schreibt
Eine einfache Möglichkeit, die in Python benötigte Zeit anzuzeigen und sie intelligenter zu verbessern
Setzen Sie Ubuntu in Raspi ein, setzen Sie Docker darauf und steuern Sie GPIO mit Python aus dem Container
Wahrscheinlich der einfachste Weg, um mit Python 3 ein PDF zu erstellen
In Python werden die Elemente in der Liste sortiert und als Elemente und Vielfache ausgegeben.
[Python] Ich habe das Spiel von pip installiert und versucht zu spielen
Code zum Senden von E-Mails basierend auf der Excel-E-Mail-Liste
So melden Sie sich mit Python bei AtCoder an und senden automatisch
(Memo) Bis Sie nur den gewünschten Teil von einer bestimmten Webseite extrahieren, konvertieren Sie ihn in eine Sphinx-Seite und drucken Sie ihn als PDF
Senden Sie japanische Post mit Python3
Ich möchte mit Python eine beliebige URL aus der Zeichenfolge der HTML-Quelle extrahieren
[Python] Was ist Pip? Erläutern Sie die Befehlsliste und deren Verwendung anhand aktueller Beispiele
[Python] So kratzen Sie eine lokale HTML-Datei und geben sie mit Beautiful Soup als CSV aus