در دنیای امروزی مبتنی بر داده، اتوماسیون کلید ساده‌سازی وظایف و صرفه‌جویی در زمان است. در این آموزش برای مبتدیان، من شما را از طریق فرآیند خودکار کردن صادرات داده ها از پایگاه داده PostgreSQL و ارسال آنها به عنوان پیوست ایمیل با استفاده از پایتون راهنمایی می کنم.

این راهنمای گام به گام به شما کمک می‌کند تا اصول کار با پایگاه‌های داده، دستکاری داده‌ها و ارتباطات ایمیل را درک کنید، همگی در حین خودکارسازی این فرآیندها با اسکریپت پایتون.

زمینه کسب و کار

تصور کنید بخشی از سازمانی هستید که مدیران شما انتظار گزارش هفتگی پر از بینش های ارزشمند را دارند. اما ایجاد این گزارش به دور از یک کار ساده است.

برای به دست آوردن اطلاعات مورد نیاز، باید ده پرس و جو پایگاه داده مختلف را به صورت دستی اجرا کنید، نتایج را جمع آوری کنید و سپس آنها را با دقت در یک صفحه گسترده اکسل کامپایل کنید. این یک فرآیند زمان بر و مستعد خطا است که می تواند شما را خسته کند.

در این سناریو، آیا اگر پایتون بتواند کنترل را در دست بگیرد و کل این فرآیند را برای شما انجام دهد، تغییر دهنده بازی نخواهد بود؟

این را تصور کنید: هر هفته، پایتون، بدون هیچ گونه مداخله دستی، داده‌های مورد نیاز را به‌طور یکپارچه استخراج می‌کند، آن‌ها را در یک برگه اکسل منظم جمع‌آوری می‌کند، و حتی آن‌ها را مانند ساعت برای مدیران شما ارسال می‌کند.

این آموزش به شما کمک می کند تا نحوه انجام این کار را بیاموزید. من شما را از طریق مراحل خودکارسازی این فرآیند راهنمایی می‌کنم، گزارش هفتگی یا ماهانه‌تان را سریع‌تر می‌کنم، و شما را آزاد می‌کنم تا روی کارهای مهم‌تر تمرکز کنید.

فهرست مطالب

  1. پیش نیازها
  2. چگونه محیط مجازی خود را راه اندازی کنیم
  3. نحوه تنظیم پایگاه داده نمونه
  4. نحوه تنظیم متغیرهای Logging و Environment
  5. نحوه استخراج داده ها از پایگاه داده
  6. چگونه داده های رزرو را با استفاده از BookingInfo کلاس
  7. نحوه تبدیل داده ها به برگه اکسل
  8. نحوه ترکیب عملکردها
  9. نحوه ارسال ایمیل با گزارش داده رزرو
  10. نحوه تست جریان
  11. نحوه برنامه ریزی برنامه
  12. بسته بندی

پیش نیازها

قبل از شروع، مطمئن شوید که موارد زیر را دارید:

  1. پایتون روی کامپیوتر شما نصب شده است. می توانید پایتون را از Python.org دانلود کنید.
  2. دانش اولیه زبان برنامه نویسی پایتون
  3. آشنایی با ارسال ایمیل در پایتون
  4. PostgreSQL روی کامپیوتر شما نصب شده است. می توانید PostgreSQL را از اینجا دانلود کنید.

چگونه محیط مجازی خود را راه اندازی کنیم

قبل از شروع کدنویسی، باید مطمئن شوید که تمام ابزارها و کتابخانه های لازم را نصب کرده اید.

برای اطمینان از اینکه یک محیط تمیز و ایزوله دارید، با استفاده از آن یک محیط مجازی ایجاد خواهید کرد venv.

یک دایرکتوری پروژه ایجاد کنید و در ترمینال به آن بروید:

mkdir report-automation
cd report-automation

یک محیط مجازی با نام ایجاد کنید env با استفاده از دستور زیر:

python -m venv env

Python اکنون با از پیش نصب شده ارسال می شود venv کتابخانه برای ایجاد محیط های مجازی

محیط مجازی را به این صورت فعال کنید:

source env/bin/activate

توجه: اگر در ویندوز هستید، باید از آن استفاده کنید source env/Scripts/activate برای فعال کردن محیط

باید ببینی (env) در اعلان ترمینال شما، نشان می دهد که محیط مجازی فعال شده است.

نحوه نصب کتابخانه های مورد نیاز

اکنون که محیط مجازی را ایجاد کرده اید، می توانید کتابخانه های زیر را نصب کنید:

  • psycopg2: آداپتور پایتون برای PostgreSQL که برنامه های پایتون را قادر می سازد با پایگاه های داده PostgreSQL تعامل داشته باشند.
  • pandas: یک کتابخانه همه کاره دستکاری و تجزیه و تحلیل داده برای پایتون، ایده آل برای کار با داده های ساخت یافته.
  • xlsxwriter: ماژول پایتون برای ایجاد و قالب بندی فایل های اکسل (XLSX)، مفید برای تولید گزارش ها و صفحات گسترده.

برای نصب کتابخانه ها، دستور زیر را اجرا کنید:

pip install psycopg2 pandas xlsxwriter

نحوه تنظیم پایگاه داده نمونه

در این بخش، من شما را از طریق راه اندازی یک پایگاه داده آزمایشی به نام “ایرلاین ها” راهنمایی می کنم که در طول این آموزش از آن استفاده خواهیم کرد. پایگاه داده شامل سه جدول است: bookings، flights، و airports_data.

من یک فایل اسکریپت SQL به نام در اختیار شما قرار می دهم airlines_db.sql که پایگاه داده را ایجاد می کند و آن را با داده های نمونه پر می کند. برای راه اندازی پایگاه داده، به نصب PostgreSQL روی سیستم خود نیاز دارید.

پایگاه داده را دانلود و نصب کنید

  1. فایل اسکریپت SQL “airlines_db.sql” را از اینجا دانلود کنید.
  2. ترمینال یا خط فرمان خود را باز کنید.
  3. برای نصب دیتابیس از دستور زیر استفاده کنید. مطمئن شوید که ابزارهای خط فرمان PostgreSQL را نصب کرده اید و می توانید به آن دسترسی داشته باشید psql فرمان جایگزین کردن postgres با نام کاربری PostgreSQL شما اگر متفاوت است.
psql -f airlines_db.sql -U postgres

این دستور اسکریپت SQL را اجرا کرده و پایگاه داده خطوط هوایی را با bookings، flights، و airports_data جداول

شرح طرحواره

طرح اصلی در پایگاه داده است bookings. بیایید نگاهی دقیق تر به جداول در پایگاه داده “ایرلاین ها” بیندازیم:

اسکرین شات-2023-10-29-115228
نمودار طرحواره

جدول bookings.bookings

جدول “رزروها” برای ذخیره اطلاعات مهم در مورد رزروهای انجام شده برای پروازها طراحی شده است. هر رزرو به طور منحصر به فرد توسط book_ref، که یک است character(6) رشته. این total_amount میدان یک است numeric(10,2) نوع و هزینه کل رزرو را نشان می دهد.

برای پیگیری تاریخ و زمان رزرو، جدول شامل یک book_date زمینه نوع bigint. این جدول به عنوان مخزن مرکزی برای داده های رزرو عمل می کند و برای ردیابی رزرو مسافران، هزینه ها و تاریخ رزرو ضروری است.

جدول bookings.flights

جدول “پروازها” به ثبت جزئیات جامع در مورد پروازها، از جمله اطلاعات مربوط به وضعیت آنها، زمان های برنامه ریزی شده و واقعی حرکت و رسیدن، و سایر داده های مهم مرتبط با پرواز اختصاص دارد.

کلید اصلی برای این جدول است flight_id، یک integer مشخص کننده. هر پرواز با شماره پرواز خاصی همراه است که با علامت نشان داده شده است flight_no میدان، الف character(6) نوع

برای درک مبدا و مقصد پرواز، departure_airport و arrival_airport فیلدها کدهای خروج و ورود فرودگاه را به عنوان ذخیره می کنند character(3) به ترتیب انواع

این status میدان یک است character varying(20) که وضعیت پرواز را ثبت می‌کند، که باید یکی از «به‌موقع»، «تأخیر افتاده»، «ورود»، «ورود»، «برنامه‌ریزی شده» یا «لغو» باشد. جدول همچنین شامل فیلدهایی برای زمان‌بندی زمان‌بندی حرکت و رسیدن (scheduled_departure و scheduled_arrival) و زمان واقعی حرکت و رسیدن (actual_departure و actual_arrival).

علاوه بر این، این جدول دو کلید خارجی ضروری را ایجاد می کند: flights_arrival_airport_fkey و flights_departure_airport_fkey، که به airport_code در جدول “airports_data”. این ارتباط بین پروازها و فرودگاه های خروج و ورود مربوطه آنها را برقرار می کند.

جدول bookings.airports_data

جدول “airports_data” به عنوان یک مخزن برای داده های مربوط به فرودگاه ها و موقعیت های جغرافیایی آنها عمل می کند. هر فرودگاه با یک فرودگاه منحصر به فرد شناسایی می شود character(3) کد ذخیره شده در airport_code فیلد که به عنوان کلید اصلی نیز عمل می کند.

این timezone زمینه، از نوع text، منطقه زمانی خاص فرودگاه را ثبت می کند و اطلاعات ضروری را برای اهداف برنامه ریزی و عملیاتی ارائه می دهد. این airport_name میدان یک است character varying تایپی که نام فرودگاه را در خود دارد. علاوه بر این، جدول شامل city میدان به عنوان یک character varying نوع، نشان دهنده شهری که فرودگاه در آن واقع شده است.

این جزئیات جدول “airports_data” را قادر می سازد تا یک نمای کلی از مکان ها و اطلاعات فرودگاه ارائه دهد. این به عنوان یک مرجع برای جدول “پروازها” از طریق flights_arrival_airport_fkey و flights_departure_airport_fkey کلیدهای خارجی، ارتباط بین پروازها و فرودگاه های خروج و ورود مربوطه را تسهیل می کند.

نحوه تنظیم متغیرهای Logging و Environment

در این بخش، ما ورود به سیستم را برای ارائه پیام های آموزنده و رسیدگی به خطاها در سراسر کد پیکربندی می کنیم. ما همچنین متغیرهای محیطی را برای ذخیره ایمن اطلاعات حساس و پارامترهای پیکربندی تنظیم خواهیم کرد. این شیوه ها خوانایی کد، قابلیت نگهداری و امنیت را افزایش می دهند.

پیکربندی ورود به سیستم

ما از برنامه داخلی پایتون استفاده خواهیم کرد logging ماژول برای پیکربندی یک سیستم ورود به سیستم. ورود به سیستم برای ردیابی جریان اجرای کد و گرفتن اطلاعات یا خطاهای مهم ضروری است.

این logging.basicConfig متد برای تعریف قالب پیام های گزارش و تنظیم سطح ورود به سیستم فراخوانی می شود INFO.

import logging

logging.basicConfig(
    format="%(asctime)s | %(levelname)s : %(message)s", level=logging.INFO
)
  • قالب: format پارامتر فرمت پیام های گزارش را مشخص می کند. در این مورد، هر ورودی گزارش شامل یک مهر زمانی، سطح گزارش (به عنوان مثال، INFO، ERROR) و پیام گزارش واقعی است.
  • سطوح ورود به سیستم: ما سطح ورود به سیستم را به INFO، به این معنی که لاگر پیام های اطلاعاتی را ضبط می کند. همچنین می توانید از سطوح شدت بالاتر مانند WARNING یا ERROR، برای مسائل مهم تر.
پیشنهاد می‌کنیم بخوانید:  روش حذف فضاهای سفید از یک رشته در پایتون

در این آموزش می توانید در مورد ورود به پایتون اطلاعات بیشتری کسب کنید.

نحوه مدیریت متغیرهای محیطی

یک را ایجاد خواهیم کرد .env فایل برای مدیریت متغیرهای محیطی از متغیرهای محیطی برای ذخیره اطلاعات حساس و تنظیمات پیکربندی استفاده می‌شود که به ما امکان می‌دهد چنین داده‌هایی را جدا از کد نگه داریم.

در این مورد، ما متغیرهای محیطی را برای اعتبار نامه ایمیل و جزئیات اتصال پایگاه داده تنظیم می کنیم.

export EMAIL=
export PASSWORD=
export EMAIL_PORT=587
export SMTP_SERVER=smtp.gmail.com
export DB_HOSTNAME=localhost
export DB_NAME=airlines
export DB_PORT=5432
export DB_USERNAME=postgres
export DB_PASSWORD=postgres

در اینجا به تفکیک متغیرها آمده است:

  • پست الکترونیک: آدرس ایمیلی که برای ارسال ایمیل استفاده می شود.
  • کلمه عبور: رمز عبور مرتبط با حساب ایمیل.
  • EMAIL_PORT: پورت سرور ایمیل (به عنوان مثال سرور SMTP). پیش فرض 587 برای انتقال ایمن ایمیل (TLS/SSL) است.
  • SMTP_SERVER: آدرس سرور SMTP که اغلب مختص ارائه دهنده خدمات ایمیل است.
  • DB_HOSTNAME: نام میزبان یا آدرس IP سرور پایگاه داده PostgreSQL.
  • DB_NAME: نام پایگاه داده PostgreSQL.
  • DB_PORT: شماره پورت برای اتصال به پایگاه داده (پیش فرض برای PostgreSQL 5432 است).
  • DB_USERNAME: نام کاربری برای احراز هویت با پایگاه داده.
  • DB_PASSWORD: رمز عبور کاربر پایگاه داده.

حتما بدوید source .env برای بارگذاری متغیرهای محیطی

با استفاده از متغیرهای محیطی، داده‌های حساس مانند گذرواژه‌ها و اعتبارنامه‌های ایمیل را می‌توان جدا از کد نگه داشت و خطر قرار گرفتن در معرض تصادفی یا دسترسی غیرمجاز را کاهش داد. کد می تواند در زمان اجرا به این متغیرها دسترسی داشته باشد و امنیت و انعطاف پذیری در پیکربندی را تضمین کند.

نحوه استخراج داده ها از پایگاه داده

بیایید با تنظیم تنظیمات پایگاه داده شروع کنیم.

import logging
import os

logging.basicConfig(
    format="%(asctime)s | %(levelname)s : %(message)s", level=logging.INFO
)

DB_CONFIG = {
    "host": os.environ.get("DB_HOSTNAME"),
    "database": os.environ.get("DB_NAME"),
    "user": os.environ.get("DB_USERNAME"),
    "password": os.environ.get("DB_PASSWORD"),
}

این DB_CONFIG فرهنگ لغت برای ذخیره پارامترهای پیکربندی برای اتصال به پایگاه داده PostgreSQL استفاده می شود. این پارامترها شامل میزبان، نام پایگاه داده، نام کاربری و رمز عبور است. این مقادیر را می توان از طریق متغیرهای محیطی تنظیم کرد.

نحوه اتصال به پایگاه داده

قبل از استخراج داده ها از پایگاه داده، باید به پایگاه داده خود متصل شویم. ما استفاده خواهیم کرد psycopg2 کتابخانه برای اتصال به پایگاه داده PostgreSQL.

ما با تعریف a شروع می کنیم DataExporter کلاسی که حاوی متدهایی برای استخراج پایگاه داده و تولید برگه اکسل است.

class DataExporter:
    def __init__(self):
        """Initialize the DataExporter with the database configuration."""
        self.db_config = DB_CONFIG

سازنده کلاس مقدار را مقداردهی اولیه می کند DataExporter با پیکربندی پایگاه داده ذخیره شده در DB_CONFIG فرهنگ لغت.

در مرحله بعد، بیایید روشی را تعریف کنیم که به پایگاه داده متصل می شود.

...
import psycopg2

...

class DataExporter:
    def __init__(self):
        """Initialize the DataExporter with the database configuration."""
        self.db_config = DB_CONFIG

    def __connect_to_database(self) -> None:
        """
        Establish a connection to the PostgreSQL database.

        Raises:
            Exception: If a connection to the database cannot be established.
        """
        try:
            self.conn = psycopg2.connect(**self.db_config)
            self.cursor = self.conn.cursor()
            logging.info("Connected to the database")
        except Exception as e:
            logging.error(
                "Failed to connect to the database with error: %s", e)
            raise

این __connect_to_database روش private مسئول ایجاد اتصال به پایگاه داده PostgreSQL است. از آن استفاده می کند psycopg2 کتابخانه ای برای ایجاد یک اتصال و یک مکان نما برای اجرای پرس و جوهای SQL. اگر اتصال ناموفق باشد، یک خطا ثبت می کند و یک استثنا ایجاد می کند.

در اینجا می توانید درباره مدیریت استثنا در پایتون اطلاعات بیشتری کسب کنید.

نحوه واکشی داده ها از پایگاه داده

اکنون روش خصوصی دیگری را تعریف می کنیم که به پایگاه داده متصل می شود و تعداد کل رزروها و کل مبلغ را از پایگاه داده دریافت می کند.

from datetime import datetime

class DataExporter:
    ...

    def __fetch_from_database(self, start_timestamp, end_timestamp) -> list | None:
        """
        Fetch booking data from the database for a given time range.

        Args:
            start_timestamp (datetime): The start of the time range.
            end_timestamp (datetime): The end of the time range.

        Returns:
            list: A list containing booking data (num_bookings, total_amount) or None if an error occurs.
        """
        self.__connect_to_database()
        query = f"""
        SELECT COUNT(*) AS num_bookings, SUM(total_amount) AS total_amount
        FROM bookings
        WHERE book_date >= {int(start_timestamp.timestamp()) * 1000} AND book_date <= {int(end_timestamp.timestamp()) * 1000}
        """
        logging.info(
            "Exracting bookings data from database for start timestamp=%s and end_timestamp=%s",
            start_timestamp,
            end_timestamp,
        )
        result = None
        try:
            self.cursor.execute(query)
            result = list(self.cursor.fetchone())
            result.append(
                f'{start_timestamp.strftime("%d %b, %Y")} - {end_timestamp.strftime("%d %b, %Y")}'
            )
            logging.info(
                "Successfully exracted bookings data from database for start timestamp=%s and end_timestamp=%s",
                start_timestamp,
                end_timestamp,
            )
        except Exception as e:
            logging.error(
                "Error occurred while extracting bookings data from database: %s", e
            )
        return result

این روش خصوصی داده های رزرو را از پایگاه داده برای یک محدوده زمانی مشخص بازیابی می کند.

دوتا طول میکشه datetime اشیاء به عنوان آرگومان، start_timestamp و end_timestamp. همچنین یک درخواست SQL برای بازیابی تعداد رزروها و کل مبلغ رزرو برای آن محدوده زمانی ایجاد می کند.

کوئری اجرا می شود و در صورت موفقیت آمیز بودن، متد داده ها را به صورت یک تاپل برمی گرداند. ما تاپل را به یک لیست تبدیل می کنیم و بازه زمانی استخراج داده ها را به لیست اضافه می کنیم. اگر در حین تعامل پایگاه داده خطایی رخ دهد، یک خطا را ثبت می کند و برمی گرداند None.

با استفاده از روش فوق، می‌توانید داده‌های رزرو را برای بازه‌های زمانی مختلف استخراج کنید، خواه برای یک هفته، یک ماه، یک سال یا هر محدوده زمانی دلخواه شما باشد.

چگونه داده های رزرو را با استفاده از BookingInfo کلاس

در این قسمت به تعریف الف می پردازیم BookingInfo کلاس در booking_info.py، که به عنوان یک محفظه ساختاریافته برای رزرو داده های بازیابی شده از پایگاه داده عمل می کند. این کلاس اطلاعات مربوط به رزرو را در بر می گیرد و کار با داده ها و ارائه آن را آسان تر می کند.

from decimal import Decimal


class BookingInfo:
    def __init__(self, data_list: list):
        """
        Initialize BookingInfo with data from the database.

        Args:
            data_list (list): A list containing booking data (total_bookings, total_amount, timestamp).

        Note:
            The total_amount is converted to a Decimal type.

        """
        self.__total_bookings, self.__total_amount, self.__timestamp = data_list
        self.__total_amount = Decimal(self.__total_amount) if self.__total_amount else Decimal(0)

    def __str__(self) -> str:
        """
        Return a string representation of BookingInfo.

        Returns:
            str: A string in the format "Total Bookings: X, Total Amount: $Y".

        """
        return f"Total Bookings: {self.__total_bookings}, Total Amount: ${self.__total_amount}"

    def get_total_bookings(self) -> int:
        """
        Get the total number of bookings.

        Returns:
            int: The total number of bookings.

        """
        return self.__total_bookings

    def get_total_amount(self) -> Decimal:
        """
        Get the total booking amount as a Decimal.

        Returns:
            Decimal: The total booking amount.

        """
        return self.__total_amount

    def get_timestamp(self) -> str:
        """
        Get the timestamp associated with the booking data.

        Returns:
            str: The timestamp as a string.

        """
        return self.__timestamp

این BookingInfo کلاس برای سازماندهی و نمایش داده های رزرو برگشتی از پایگاه داده طراحی شده است. فهرستی از مقادیر شامل کل رزروها، کل مبلغ رزرو، و مهر زمانی را به عنوان ورودی دریافت می کند و مبلغ کل را به نوع اعشاری تبدیل می کند. کلاس روش هایی را برای دسترسی و ارائه این داده ها به صورت ساختار یافته ارائه می دهد.

سازنده از BookingInfo کلاس می گیرد a data_list به عنوان ورودی، که انتظار می رود لیستی حاوی عناصر زیر باشد:

  • total_bookings: یک عدد صحیح که تعداد کل رزروها را نشان می دهد.
  • total_amount: یک مقدار ممیز شناور که نشان دهنده کل مبلغ رزرو است.
  • timestamp: مهر زمانی مرتبط با داده های رزرو.

این __init__ متد متغیرهای نمونه خصوصی را مقداردهی اولیه می کند (__total_bookings، __total_amount، و __timestamp) با مقادیر از data_list. آن را نیز تبدیل می کند __total_amount به نوع اعشاری برای مدیریت دقیق مقادیر پولی.

این __str__ متد برای ارائه یک نمایش رشته ای پیاده سازی شده است BookingInfo هدف – شی. یک رشته با فرمت «کل رزروها: X، مبلغ کل: $Y»، جایی که X تعداد کل رزرو و Y مبلغ کل رزرو است که به صورت دلار قالب بندی شده است.

روش های گتر

کلاس سه روش دریافت کننده برای دسترسی به داده های کپسوله شده ارائه می دهد:

  • get_total_bookings(): تعداد کل رزروها را به صورت یک عدد صحیح برمی گرداند.
  • get_total_amount(): کل مبلغ رزرو را به صورت اعشاری برمی گرداند.
  • get_timestamp(): مهر زمانی مرتبط با داده های رزرو را به صورت رشته ای برمی گرداند.

با کپسوله کردن داده های رزرو در داخل BookingInfo کلاس، کد سازماندهی شده، خوانا و قابل استفاده مجددتر است. این رویکرد ساختاریافته مدیریت اطلاعات رزرو را در سراسر برنامه ساده می‌کند و کار با و ارائه داده‌ها را بصری‌تر می‌کند.

نحوه تبدیل داده ها به برگه اکسل

اکنون که می توانید داده ها را از پایگاه داده برای یک محدوده زمانی خاص بازیابی کنید، می توانید یک برگه اکسل نیز بر اساس داده های استخراج شده ایجاد کنید.

برای این کار، بیایید یک روش خصوصی دیگر برای ایجاد برگه اکسل تعریف کنیم.

...
import pandas as pd

from booking_info import BookingInfo


...

class DataExporter:

	...

    def __convert_to_excelsheet(self, data: list, sheet_name: str):
        """
        Convert the fetched data into an Excel sheet.

        Args:
            data (list): A list containing booking data.
            sheet_name (str): Name of the Excel sheet to be created.

        Raises:
            ValueError: If there is an error in converting data to an Excel sheet.
        """
        try:
            booking_info = BookingInfo(data)
            data = {
                "": ["Total Bookings", "Total Amount ($)"],
                booking_info.get_timestamp(): [
                    booking_info.get_total_bookings(),
                    booking_info.get_total_amount(),
                ],
            }
            logging.info("Converting the data into pandas dataframe")
            df = pd.DataFrame(data)
            logging.info("Inserting the data into the excelsheet")
            with pd.ExcelWriter(sheet_name, engine="xlsxwriter") as writer:
                df.to_excel(writer, sheet_name="Sheet1", index=False)
            logging.info("Successfully inserted data into the excelsheet")
        except ValueError as e:
            logging.error("Error converting data into excel: %s", e)

این __convert_to_excelsheet روش در DataExporter کلاس مسئول ساختاردهی و تبدیل داده های رزرو استخراج شده به برگه اکسل است.

دو پارامتر ورودی را می پذیرد. پارامتر اول، data، انتظار می رود لیستی حاوی داده های رزرو خاص باشد. این داده ها شامل تعداد کل رزروها، کل مبلغ رزرو و مهر زمانی است که داده ها برای آن استخراج شده است. پارامتر دوم، sheet_name، نشان دهنده نام مورد نظر برای برگه اکسل است که حاوی داده های فرمت شده است.

پیشنهاد می‌کنیم بخوانید:  چرا کد پایتون در یک تابع سریعتر اجرا می شود؟

یکی از جنبه های کلیدی روش، ساختار داده ها است. برای رسیدن به این هدف، روش ایجاد a را آغاز می کند BookingInfo شی، به عنوان booking_info. این BookingInfo شی یک نمایش ساختار یافته از داده های رزرو را ارائه می دهد که قالب بندی و ارائه بعدی را ساده می کند.

به دنبال ایجاد booking_info شی، یک فرهنگ لغت جدید به نام data تولید می شود. این فرهنگ لغت به گونه ای طراحی شده است که داده ها را در قالبی مناسب برای تبدیل به صفحه اکسل ساختار دهد.

فرهنگ لغت از دو جفت کلید-مقدار تشکیل شده است:

  • جفت اول از یک رشته خالی به عنوان کلید استفاده می کند و حاوی لیستی با دو مقدار سرصفحه، “Total Bookings” و “Total Amount ($)” است.
  • جفت دوم از مهر زمانی به دست آمده از استفاده می کند booking_info.get_timestamp() به عنوان کلید و شامل لیستی با دو عنصر: تعداد کل رزروها (booking_info.get_total_bookings()) و مبلغ کل رزرو (booking_info.get_total_amount()).

این فرهنگ لغت اجازه می دهد تا داده ها را به صورت زیر در برگه اکسل درج کنید:

اسکرین شات-2023-10-29-135512
نمونه برگه اکسل

سپس، ساختار یافته data فرهنگ لغت به یک DataFrame پاندا تبدیل می شود که به آن اشاره می شود df. Dataframe ها یک ساختار داده رایج برای مدیریت داده های جدولی در پایتون هستند. این مرحله دستکاری و صادرات داده ها را برای پردازش یا تجسم بیشتر ساده می کند.

برای ایجاد برگه اکسل، کد از pd.ExcelWriter مدیر زمینه با موتور “xlsxwriter”. این مدیر زمینه اطمینان حاصل می کند که فایل اکسل به طور مناسب برای درج داده ها آماده شده است. این sheet_name پارامتر برای تعیین نام برگه در فایل اکسل ارائه می شود.

داده های درون DataFrame، df، سپس در برگه اکسل نوشته می شود. این to_excel روش در ارتباط با استفاده می شود writer شیء، و index پارامتر تنظیم شده است False. این پیکربندی خاص، اعداد ردیف پیش‌فرض را که معمولاً در برگه‌های اکسل گنجانده شده‌اند، حذف می‌کند.

نحوه ترکیب عملکردها

حالا بیایید یک روش عمومی بنویسیم که کاربران بتوانند از آن برای استخراج داده ها از پایگاه داده و تبدیل داده های استخراج شده به فایل اکسل استفاده کنند.

...


class DataExporter:
	
    ...
    
    def generate_excelsheet(
        self,
        start_timestamp: datetime,
        end_timestamp: datetime,
        sheet_name: str = "Bookings Data.xlsx",
    ) -> bool:
        """
        Generate an Excel sheet with booking data for a specified time range.

        Args:
            start_timestamp (datetime): The start of the time range.
            end_timestamp (datetime): The end of the time range.
            sheet_name (str, optional): Name of the Excel sheet to be created. Defaults to "Bookings Data.xlsx".

        Returns:
            bool: True if excelsheet was generated successfully else False

        Note:
            This method logs errors but does not raise exceptions to avoid breaking the workflow.
        """
        data = self.__fetch_from_database(start_timestamp, end_timestamp)
        if data is not None:
            self.__convert_to_excelsheet(data, sheet_name)
            return True
        else:
            logging.error("No data to convert generate excelsheet")
            return False

این روش چندین پارامتر از جمله start_timestamp و end_timestamp، که شروع و پایان دوره زمانی استخراج داده ها را مشخص می کند. اختیاری نیز وجود دارد sheet_name پارامتری که به کاربر اجازه می دهد نام برگه اکسل را مشخص کند. به‌طور پیش‌فرض، برگه «Bookings Data.xlsx» نام دارد تا یک گزینه پیش‌فرض مناسب ارائه دهد.

پس از اجرا، متد با فراخوانی فرآیند بازیابی داده ها را آغاز می کند __fetch_from_database متد، یک متد خصوصی داخلی کلاس، با محدوده زمانی مشخص شده است.

اگر بازیابی داده ها موفقیت آمیز باشد و داده ها در دسترس باشد، روش به فراخوانی ادامه می دهد __convert_to_excelsheet روش. این داده ها را برای درج در برگه اکسل ساختار و قالب بندی می کند.

از طرف دیگر، اگر هیچ داده ای برای محدوده زمانی ارائه شده در دسترس نباشد، روش یک پیام خطا را ثبت می کند و “False” را برمی گرداند تا نشان دهد که تولید برگه اکسل ناموفق بوده است.

نحوه ارسال ایمیل با گزارش داده رزرو

در این بخش، یاد خواهید گرفت که چگونه می توانید از پایتون برای ارسال ایمیل با گزارش داده های رزرو به عنوان پیوست استفاده کنید.

ایجاد یک mailer.py فایل و محتوای زیر را اضافه کنید:

import logging
import os
import smtplib
import ssl

from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

logging.basicConfig(
    format="%(asctime)s | %(levelname)s : %(message)s", level=logging.INFO
)

SMTP_SERVER = os.environ.get("SMTP_SERVER")
PORT = os.environ.get("EMAIL_PORT")
EMAIL = os.environ.get("EMAIL")
PASSWORD = os.environ.get("PASSWORD")


def send_email(to_email: str, subject: str, attachment_name: str):
    """
    Send an email with an attachment to the specified recipient.

    Args:
        to_email (str): The recipient's email address.
        subject (str): The subject of the email.
        attachment_name (str): The filename of the attachment.

    Note:
        This function assumes that the SMTP server requires TLS encryption.

    Raises:
        smtplib.SMTPException: If there is an issue with sending the email.

    """
    message = MIMEMultipart()
    message["From"] = EMAIL
    message["To"] = to_email
    message["Subject"] = subject
    body = "Hi there\n\nPlease find attached your report.\n\nThanks"

    message.attach(MIMEText(body, "plain"))

    with open(attachment_name, "rb") as file:
        part = MIMEBase(
            "application", "vnd.openxmlformats-officedocument.spreadsheetml.sheet"
        )
        part.set_payload(file.read())

    encoders.encode_base64(part)

    part.add_header(
        "Content-Disposition",
        f"attachment; filename= {attachment_name}",
    )

    logging.info(f"Attaching {attachment_name} to the email")
    message.attach(part)
    text = message.as_string()

    context = ssl.create_default_context()
    with smtplib.SMTP(SMTP_SERVER, PORT) as server:
        logging.info(f"Sending email to {to_email}")
        server.starttls(context=context)
        server.login(EMAIL, PASSWORD)
        server.sendmail(EMAIL, to_email, text)
        logging.info(f"Successfully sent the email to {to_email}")

طبق معمول، ما متغیرهای لاگر و محیط را در اسکریپت خود پیکربندی کرده ایم.

عملکرد اصلی در داخل کپسوله شده است send_email تابع. این تابع سه پارامتر دارد:

  1. to_email: آدرس ایمیل گیرنده.
  2. subject: موضوع ایمیل.
  3. attachment_name: نام فایل پیوست، که باید گزارش داده رزرو در این زمینه باشد.

در داخل تابع، یک پیام ایمیل با استفاده از MIMEMultipart کلاس این پیام شامل آدرس ایمیل فرستنده، آدرس ایمیل گیرنده، موضوع و متن ساده با یک پیام ساده است.

اسکریپت اجازه می دهد تا گزارش داده های رزرو را به عنوان پیوست پیوست کنید. فایل پیوست را می خواند، آن را رمزگذاری می کند و به پیام ایمیل اضافه می کند. این تضمین می‌کند که گیرنده به راحتی می‌تواند به گزارش داده‌ها از ایمیل دسترسی داشته باشد و آن را دانلود کند.

در اینجا می توانید یاد بگیرید که چگونه می توانید هنگام ارسال ایمیل با استفاده از پایتون، پیوست اضافه کنید.

این create_default_context تابع از ssl کتابخانه یک زمینه SSL امن برای ارتباط ایمیل ایجاد می کند. در نهایت، اسکریپت به سرور SMTP متصل می شود، با استفاده از آدرس ایمیل و رمز عبور فرستنده وارد سیستم می شود، ایمیل را ارسال می کند و پس از ارسال موفقیت آمیز، پیام موفقیت آمیز را ثبت می کند.

نحوه تست جریان

اجازه دهید در نهایت جریان برنامه را آزمایش کنیم.

بالاخره در مورد زمان

در این بخش گزارش های ماهانه را خودکار می کنیم. ایجاد یک main.py فایل و محتوای زیر را اضافه کنید:

from exporter import DataExporter
from datetime import datetime
from mailer import send_email

start_timestamp = datetime(1402, 5, 28, 00, 00, 00)  # May 28 1402 00:00:00
end_timestamp = datetime(1402, 8, 20, 23, 59, 59)  # Aug 20 1402 23:59:59

exporter = DataExporter()
if exporter.generate_excelsheet(
        start_timestamp, end_timestamp, sheet_name="Bookings Data.xlsx"):
    send_email("myemail@gmail.com", "Your Report", "Bookings Data.xlsx")

در کد بالا، دو شیء برچسب زمانی ایجاد می کنیم، start_timestamp و end_timestamp، برای تعیین محدوده زمانی. ما تاریخ شروع را در 28 مه 1402 در نیمه شب و تاریخ پایان را تا 20 اوت 1402 درست قبل از نیمه شب تعیین کرده ایم.

بعد، یک نمونه از the ایجاد می کنیم DataExporter کلاس، که صادرات داده و تولید برگه اکسل را مدیریت می کند. این generate_excelsheet روش این نمونه با مهرهای زمانی تعریف شده قبلی برای ایجاد گزارش مربوط به رزرو فراخوانی می شود.

در نهایت، کد یک ایمیل با برگه اکسل تولید شده به عنوان پیوست با استفاده از send_email تابع.

نحوه برنامه ریزی برنامه

در مرحله بعد، هدف ما خودکار کردن فرآیند زمان‌بندی گزارش است. هدف ما برنامه‌ریزی تحویل گزارش‌ها برای دو سناریو متمایز است: هر دوشنبه برای داده‌های هفته قبل، و در روز اول هر ماه برای اطلاعات ماه قبل.

برای برنامه ریزی اجرا، باید آن را نصب کنید schedule کتابخانه:

pip install schedule

پس از نصب کتابخانه، در اینجا نحوه خودکارسازی گزارش های ماهانه و هفتگی آورده شده است:

import schedule
from exporter import DataExporter
from datetime import datetime, timedelta
from mailer import send_email


def main():
    today = datetime.now()
    sheet_name = "Bookings Data.xlsx"

    if today.weekday() == 0:  # Check if it's Monday (0 means Monday)
        # It's Monday, fetch data for the previous week (Monday to Sunday)
        start_timestamp = (today - timedelta(days=7)
                           ).replace(hour=0, minute=0, second=0, microsecond=0)
        end_timestamp = (today - timedelta(days=1)
                         ).replace(hour=23, minute=59, second=59, microsecond=0)
        sheet_name = "Weekly Report.xlsx"
    elif today.day == 29:
        # It's the 1st day of the month, fetch data for the last month
        start_timestamp = (today.replace(day=1) - timedelta(days=1)
                           ).replace(day=1, hour=0, minute=0, second=0, microsecond=0)
        end_timestamp = (today.replace(day=1) - timedelta(days=1)
                         ).replace(hour=23, minute=59, second=59, microsecond=0)
        sheet_name = "Monthly Report.xlsx"

    exporter = DataExporter()
    exporter.generate_excelsheet(
        start_timestamp, end_timestamp, sheet_name)

    send_email("youremail@gmail.com",
               "Your Report", sheet_name)


schedule.every().day.at("00:00").do(main)

while True:
    schedule.run_pending()

اسکریپت بالا از schedule کتابخانه برای اجرا main عملکرد روزانه در نیمه شب این main تابع، مهرهای زمانی استخراج داده و تولید برگه اکسل را محاسبه می کند. پس از تولید برگه اکسل، اسکریپت آن را از طریق ایمیل به یک گیرنده مشخص ارسال می کند.

اگر اسکریپت در روز دوشنبه اجرا شود، برای تولید یک گزارش هفتگی تنظیم می شود. را محاسبه می کند start_timestamp و end_timestamp برای هفته قبل این start_timestamp به دوشنبه قبل در نیمه شب (00:00:00) تنظیم شده است و end_timestamp به یکشنبه قبل درست قبل از نیمه شب (23:59:59) تنظیم شده است. برگه اکسل “Weekly Report.xlsx” نام دارد.

در روز اول ماه، اسکریپت تمرکز خود را به تولید گزارش ماهانه تغییر می‌دهد. را محاسبه می کند start_timestamp و end_timestamp کل ماه قبل را در بر گیرد. این start_timestamp به اولین روز ماه قبل در نیمه شب (00:00:00) تنظیم شده است، در حالی که end_timestamp به آخرین روز ماه قبل درست قبل از نیمه شب (23:59:59) تنظیم شده است. برگه اکسل “گزارش ماهانه.xlsx” نام دارد.

بسته بندی

در این آموزش، یاد گرفتید که چگونه می توانید از پایتون برای تولید خودکار گزارش و ارسال آن به گیرندگان ایمیل استفاده کنید. امیدوارم آموزش برای شما مفید بوده باشد!

حوزه آینده

  • می‌توانید گیرندگان ایمیل را در یک پایگاه داده اضافه کنید و به جای اینکه آنها را در خود کد کدگذاری کنید، لیست آنها را از آنجا واکشی کنید. این باعث می شود که برنامه قابل تنظیم تر شود.
  • همچنین می توانید از Cron Jobs برای خودکار کردن اجرای اسکریپت هر روز در نیمه شب استفاده کنید. در آن صورت، شما به آن نیاز نخواهید داشت schedule کتابخانه

در اینجا پیوندی به مخزن کد Github وجود دارد.