Ninja Learn | نینجا لرن
1.26K subscribers
96 photos
36 videos
11 files
307 links
یادگیری برنامه نویسی به سبک نینجا 🥷
اینجا چیزایی یاد میگیری که فقط نینجاهای وب‌ بلدن 🤫

📄 Send me post: https://t.me/NoronChat_bot?start=sec-fdggghgebe

👥 ɢʀᴏᴜᴘ: https://t.me/+td1EcO_YfSphNTlk
Download Telegram
🚀 معرفی FastAPI

ـ FastAPI یه فریم ورک پایتونیه که باهاش میشه داخل پایتون api توسعه داد که تازگیا خیلییی بین پایتون کارا سرو و صدا کرده.
ـFastAPI یه فریم‌ورک مدرن برای ساختن APIبا پایتون و ویژگی هایی مثل async/await که بهینه شده و... . خیلی از شرکت‌های بزرگ مثل Netflix و Uber برای توسعه سرویس‌هاشون از FastAPI استفاده می‌کنن، و دلیلش هم مشخصه: سریع، ساده و انعطاف‌پذیره.

💡 چرا FastAPI محبوبه؟
سریع‌ترین فریم‌ورک پایتون: FastAPI به لطف استفاده از Starlette و Pydantic، یکی از سریع‌ترین فریم‌ورک‌های پایتون حساب می‌شه.

کدنویسی سریع‌تر: تایپ‌هینت‌های پایتون باعث می‌شه نوشتن کدها هم سریع‌تر باشه و هم باگ‌های کمتری داشته باشی.

مستندات خودکار: یکی از بهترین ویژگی‌های FastAPI اینه که خودش به‌طور اتوماتیک با Swagger UI و ReDoc مستندات API رو برات می‌سازه.

پشتیبانی از async/await: فست خیلی خوب از کدونیسی async ساپورت میکنه و یکی از دلایل محبوبیتشه.

🛠 ـFastAPI و کار با دیتابیس
وقتی می‌خوای با دیتابیس کار کنی، معمولاً از ORMها استفاده می‌کنی. تو FastAPI دو تا گزینه معروف داریم:
ـSQLAlchemy
ـSQLModel
حالا کدوم بهتره؟ بیاین دقیق‌تر بررسی کنیم:

ـ🔍 SQLAlchemy؛ قدیمی و قدرتمند
ـSQLAlchemy یکی از معروف‌ترین ORMها برای پایتونه که زیاد استفاده میشه. انعطاف‌پذیری بالایی داره و برای پروژه‌های پیچیده و بزرگ گزینه خیلی خوبیه.
مزیت‌ها:
کنترل کامل روی کوئری‌ها و عملکرد دیتابیس
پشتیبانی از تراکنش‌ها و مدل‌های پیچیده
جامعه کاربری بزرگ و منابع آموزشی زیاد
چالش‌ها:
سینتکسش برای تازه‌کارها ممکنه سخت و پیچیده باشه
نوشتن کدهای زیاد برای مدل‌سازی

ـ🌀 SQLModel؛ ساده و مدرن
ـSQLModel یه کتابخونه جدیدتره که توسط خالق FastAPI یعنی Sebastián Ramírez توسعه داده شده. هدف SQLModel اینه که کار با دیتابیس رو ساده‌تر کنه و کدنویسی رو شبیه به Pydantic (برای ولیدیشن) بکنه.
مزیت‌ها:
سینتکس خیلی ساده و خوانا
پشتیبانی از تایپ‌هینت‌های پایتون
هماهنگی عالی با FastAPI
کمتر شدن کدنویسی و مدل‌سازی سریع
چالش‌ها:
هنوز نسبت به SQLAlchemy به بلوغ کامل نرسیده
برای پروژه‌های خیلی پیچیده ممکنه محدودیت‌هایی داشته باشه

مقایسه کدها
مدل‌سازی با SQLAlchemy:
from sqlalchemy import Column, Integer, String  
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True)


مدل‌سازی با SQLModel:
from sqlmodel import SQLModel, Field  

class User(SQLModel, table=True):
id: int = Field(default=None, primary_key=True)
name: str = Field(index=True)


همون‌طور که می‌بینید، SQLModel خیلی تمیزتر و کوتاه‌تره و شبیه به Pydantic می‌شه.

🎯 بالاخره SQLAlchemy یا SQLModel؟
اگه تازه‌کار هستی یا پروژه‌ت کوچیکه و می‌خوای سریع کارت راه بیفته، SQLModel گزینه بهتریه. سینتکس ساده‌ای داره و هماهنگیش با FastAPI عالیه.
ولی اگه پروژه‌ت بزرگه یا نیاز به کنترل کامل و قابلیت‌های بیشتر ORM داری ، SQLAlchemy انتخاب بهتریه.
خلاصه:
پروژه‌های کوچیک و متوسط SQLModel
پروژه‌های بزرگ و پیچیده SQLAlchemy

امید وارم مفید بوده باشه :)

#python #fastapi


🔆 CHANNEL | GROUP
21👍5
خب خب خب Sentry چیه؟ 🔍

اگه برنامه نویسی میکنی احتمالاً این سناریو برات آشناست:
کلی وقت می‌ذاری، کد می‌نویسی، تست می‌کنی، همه‌چی درست کار می‌کنه. ولی وقتی می‌دی دست کاربر، یهو یه ارور عجیب غریب میاد که اصلاً نمی‌دونی از کجا دراومده اینجاست که Sentry وارد بازی میشه.

ـSentry چیه اصلاً؟
ـSentry یه ابزار خطایاب (Error Tracking) که کمک می‌کنه باگ‌ها و خطاهای پروژه‌ت رو همون لحظه‌ای که اتفاق میفتن، پیدا کنی.
این ابزار نه‌تنها ارورها رو جمع‌آوری می‌کنه، بلکه یه گزارش دقیق و کامل ازشون می‌ده؛ از جزئیات خطا گرفته تا شرایطی که باعث شده ارور پیش بیاد.
فرض کن یه باگ تو اپلیکیشن‌ ته که اصلاً قابل پیش‌بینی نبوده. به‌جای اینکه کاربر بیاد غر بزنه یا خودت بری تو لاگ‌ها دنبال مشکل بگردی، Sentry خودش ارور رو تشخیص می‌ده و گزارشش رو مستقیم برات می‌فرسته.

چرا Sentry محبوبه؟ 🌟
1⃣ گزارش ارور دقیق و کاربردی 🛠️
وقتی یه ارور اتفاق میفته، Sentry دقیقاً بهت میگه مشکل کجاست. جزئیاتی مثل:
فایل و خط کدی که ارور داده
نوع خطا (Exception)
اطلاعات مرورگر یا دستگاه کاربر
وضعیت سرور (مثلاً رم و CPU)
حتی مراحل درخواست کاربر تا لحظه‌ای که ارور رخ داده

2⃣ پشتیبانی از پلتفرم‌های مختلف 📱
هرچی فکرش رو بکنی، Sentry ساپورتش میکنه.
Backend: Python (جنگو، فلاسک و ...)، Node.js
Frontend: React، Vue.js
Mobile: اندروید و iOS
DevOps: Docker، Kubernetes


3⃣ دسته‌بندی ارورها 🗂️
وقتی تعداد ارورها زیاد بشه، Sentry اونا رو گروه‌بندی می‌کنه. مثلاً یه باگ اگه صد بار اتفاق بیفته، همشون رو زیر یه گزارش می‌ذاره که بتونی راحت مدیریت کنی.

4⃣ هشدار و نوتیفیکیشن 🔔

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


5⃣ـ Release Tracking 🚀
یه قابلیت جالبش اینه که می‌تونی ارورها رو به نسخه‌های پروژت وصل کنی و بفهمی کدوم تغییرات باعث مشکل شده.


6⃣ـPerformance Monitoring
علاوه بر ارورها، می‌تونی بفهمی اپلیکیشن کجاها کنده.


چطور از Sentry استفاده کنیم؟
ثبت‌نام کن:
تو سایت Sentry.io یه اکانت بساز. نسخه رایگانش برای شروع کافیه.

نصب کن:
ـSDK مخصوص زبان پروژه‌ت رو نصب کن. مثلاً برای Django این دستور کافیه:
 pip install sentry-sdk 

تنظیمش کن:
با چند خط کد ساده Sentry رو به پروژه وصل کن:
import sentry_sdk
sentry_sdk.init(
dsn="لینک DSN که Sentry می‌ده",
traces_sample_rate=1.0
)

ارورها رو مدیریت کن:
حالا هر اروری اتفاق بیفته، مستقیم تو داشبورد Sentry میره.

چند نکته مهم:
نسخه رایگان Sentry محدودیت داره (مثلاً تعداد ارورهای ماهانه). برای پروژه‌های بزرگ باید پلن‌های پولیش رو بگیری.
می‌تونی از مستندات رسمی کمک بگیری تا تنظیمات حرفه‌ای‌تر انجام بدی.

جمع‌بندی
اگه می‌خوای ارورهای پروژه‌ت رو حرفه‌ای مدیریت کنی و حتی قبل از اینکه کاربر بفهمه، خودت رفعشون کنی، Sentry بهترین انتخابه. هم راحت نصب میشه، هم کلی قابلیت خفن داره.
تا حالا از Sentry استفاده کردی؟ نظرت چیه؟ 👀

#programming #python #sentry



🔆 CHANNEL | GROUP
17
تا حالا کلی مطالب خفن و کاربردی تو کانال NinjaLearn براتون آماده کردیم و الان صدها مطلب مختلف و جذاب داریم.

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

این شما و این لیست دسته‌بندی‌های کانال🔻:

🦫 #go: آموزش‌ها و نکات کاربردی زبان گو

💻 #programming: مطالب برنامه نویسی

🐍 #python: ترفندها و نکات پایتونی

🦄 #django: مطالب فریم‌ورک جنگو

⚡️ #fastapi: مطالب فریم ورک فست

🌐 #web: مطالب مرتبط به وب

📡 #network: مطالب مرتبط به شبکه

🗂️ #db: معرفی و نکات دیتابیس

🔖 #reference: معرفی مقاله و ویدیو

📢 #notif: اطلاع رسانی ها

#question: سوالات جالب در برنامه نویسی

🎊 #event: رویداد هایی که معرفی کردیم

🎬 #movie: معرفی فیلم و سریال

📚 #book: معرفی کتاب‌های تخصصی

🤖 #AI: مطالب مرتبط به هوش مصنوعی

📊 #ml: مطالب مرتبط به یادگیری ماشین

🛠️ #backend: آموزش‌ها و ترفندهای بک‌اند

🔒 #security: نکات امنیتی

#devops: مطالب مرتبط به دواپس

📺 #YouTube: ویدیوهای چنل یوتیوب ما


هر کدوم از این هشتگ‌ها برای یه موضوع خاص طراحی شده تا شما به راحتی بتونید محتوای مورد نظرتون رو پیدا کنید. دیگه لازم نیست کلی تو کانال بگردید 😊

اگه موضوع جدیدی به مطالب کانال اضافه بشه، حتماً تو این لیست قرار می‌گیره


راستی میتونید بنر کانال رو برای دوستاتون هم بفرستید تا اونا هم به جمع ما بپیوندن و از این مطالب مفید استفاده کنن 😉

NinjaLearn Banner 🥷🤝


#category



🔆 CHANNEL | GROUP
22👍1👎1🔥1
خب خب خب شی‌گرایی در پایتون🚀

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

1⃣ متاکلاس‌ها🕵️‍♂️
متاکلاس‌ها این امکان رو می‌دن که قبل از ایجاد یک کلاس، ساختارش رو کنترل کنی. می‌تونی مطمئن شی که قوانین خاصی رعایت شدن یا حتی رفتار کلاس رو دستکاری کنی.
مثال:
اطمینان از تعریف متد greet در کلاس
class Meta(type):
def __new__(cls, name, bases, dct):
# Ensure 'greet' method exists in the class
if 'greet' not in dct:
raise TypeError(f"Class '{name}' must define 'greet' method")
return super().__new__(cls, name, bases, dct)

class MyClass(metaclass=Meta):
def greet(self):
return "Hello, world!"

obj = MyClass()
print(obj.greet()) # Output: Hello, world!

💡 چی شد؟
متاکلاس Meta بررسی می‌کنه که متد greet توی هر کلاسی که ازش استفاده می‌کنه، حتماً تعریف شده باشه. با این کار، خطاها زودتر شناسایی می‌شن و کدت تمیزتر می‌مونه.
2⃣ ‏Composition به جای ارث‌بری 🔗
ترکیب یا Composition یک راه انعطاف‌پذیرتر برای ساختار دادن به کلاسهات هست. این روش بهت کمک می‌کنه وابستگی‌ها رو کم کنی و کدهات قابل نگهداری‌تر باشن.
مثال: تعریف ماشین با استفاده از موتور
class Engine:
def start(self):
return "Engine started"

class Car:
def __init__(self):
self.engine = Engine() # Engine is a part of Car

def start(self):
return self.engine.start() # Delegate starting to Engine

car = Car()
print(car.start()) # Output: Engine started

💡 چی شد؟
به جای این که ماشین از موتور ارث‌بری کنه، موتور به عنوان یک جزء در ماشین ترکیب شده. این یعنی موتور رو می‌تونی راحت عوض کنی بدون این که ساختار کلی ماشین به مشکل بخوره.
3⃣ بهینه‌سازی حافظه با slots 🧠
ویژگی های (attributes) هر آبجکت در پایتون به صورت پیش‌فرض در یک دیکشنری ذخیره می‌شن که حافظه زیادی مصرف می‌کنه. با slots می‌تونی این دیکشنری رو حذف کنی و مصرف حافظه رو کاهش بدی.
مثال: استفاده از slots برای بهینه‌سازی

class MyClass:
__slots__ = ['name', 'age'] # Restrict attributes to these two

obj = MyClass()
obj.name = "Alice"
obj.age = 25

💡 چی شد؟
ویژگی‌های آبجکت فقط محدود به name و age هستن و هیچ فضای اضافی برای دیکشنری داخلی استفاده نمی‌شه. این روش توی سیستم‌هایی با تعداد آبجکت زیاد، تفاوت بزرگی ایجاد می‌کنه.

4⃣ ‏Abstract Base Classes 🎯
کلاس‌های پایه انتزاعی (ABC) تضمین می‌کنن که کلاس‌های فرزند متدهای مشخصی رو پیاده‌سازی کنن. این کار طراحی رو مطمئن‌تر و کدها رو خواناتر می‌کنه.
مثال: طراحی یک کلاس پایه برای اشکال هندسی
from abc import ABC, abstractmethod

class Shape(ABC):
@abstractmethod
def area(self):
"""Calculate the area of the shape"""
pass

class Circle(Shape):
def __init__(self, radius):
self.radius = radius

def area(self):
return 3.14 * self.radius ** 2 # Area formula for a circle

circle = Circle(5)
print(circle.area()) # Output: 78.5

💡 چی شد؟
کلاس Shape تضمین می‌کنه که همه‌ی اشکال فرزند متد area رو داشته باشن. بدون این متد، ساختن کلاس فرزند امکان‌پذیر نیست.

جمع‌بندی
این نکات فقط نوک کوه یخه اگه می‌خوای عمیق تر بشی، کتاب Fluent Python یکی از بهترین منابعه.

#programming #python #oop



🔆 CHANNEL | GROUP
1👍14🔥21
class MetaLoggernew
def __new__(meta_cls, cls_name, bases, cls_dict):
print(f"داریم کلاس {cls_name} رو می‌سازیم!")
new super().__new__(meta_cls, cls_name, bases, clsinit

def __init__(cls, cls_name, bases, cls_dict):
print(f"کلاس {cls_name} ساخته شده و آماده استفاده است!")

initsuper().__init__(cls_name, bases, cls_dict)

class Example(metaclass=MetaLogger):
pass

# خروجی:
# داریم کلاس Example رو می‌سازیم!
# کلاس Example ساخته شده و آماده استفاده است

5⃣ مزایا و چالش‌های متاکلاس‌ها 💡⚠️
مزایا:
کنترل دقیق روی ساختار کلاس‌ها:
می‌توانید رفتار و ساختار کلاس‌ها رو به دلخواه تغییر بدید.
کاهش تکرار کد:
الگوها و قوانین مشترک رو در یک نقطه متمرکز می‌کنید.

ایجاد چارچوب‌های پیچیده:
برای ساخت فریمورک‌های پیشرفته (مثل Django یا SQLAlchemy) این تکنیک فوق‌العاده کاربردیه.

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

اشکال‌زدایی سخت‌تر:
خطاها در متاکلاس‌ها معمولاً در زمان ایجاد کلاس اتفاق می‌افتند و پیدا کردشون سخت تر هست.

استفاده بیش از حد:
همیشه باید از متاکلاس‌ها تنها در وقتایی استفاده کنید که واقعاً نیاز دارید؛ بعضی وقتی راه‌حل‌های ساده‌تر مانند دکوریتورها یا میکسین‌ها کفایت میکنن.

7⃣ جمع‌بندی نهایی
متاکلاس‌ها به شما این امکان رو میدن که قبل از ساخته‌شدن کلاس، رفتار و ساختار اون رو تغییر بدید. اگه نیاز به کنترل دقیق روی ساختار کد دارید یا میخواید چارچوب‌های پیچیده‌ای بسازید، متاکلاس‌ها ابزار قدرتمندی هستن. اما همزمان باید به خاطر داشته باشید که این جادوی عمیق نیازمند دانش و دقت بالایی هست.

امید وارم مفید بوده باشه :)

#⃣ #python #programming



🥷 CHANNEL | GROUP
👍102
خب خب خب دکوریتورها (Decorators) در پایتون: تغییر رفتار توابع و کلاس‌ها 🐍

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

1⃣ دکوریتورها چیستند؟ 🤔
دکوریتورها در پایتون، توابع یا کلاس‌هایی هستن که مثل یه "بسته‌بندی" عمل می‌کنن. یعنی، شما یه تابع یا کلاس رو می‌گیرید، اون رو به یه دکوریتور می‌فرستید، دکوریتور رفتارش رو تغییر می‌ده (یا بهبود می‌بخشه) و نسخه تغییر یافته رو برمی‌گردونه.

مثال ساده:
def simple_decorator(func):
def wrapper(*args, **kwargs):
print("قبل از اجرای تابع")
result = func(*args, **kwargs)
print("بعد از اجرای تابع")
return result
return wrapper

@simple_decorator
def greet(name):
print(f"سلام، {name}!")

greet("علی")

اینجا دکوریتور simple_decorator قبل و بعد از اجرای تابع greet پیام چاپ می‌کنه. یعنی بدون اینکه کد اصلی تابع رو دست بزنیم، رفتارش تغییر پیدا می‌کنه.

2⃣ نحوه‌ی کارکرد دکوریتورها 🔧

🔻 دکوریتور به عنوان یک تابع
در واقع، دکوریتورها توی پایتون همون توابعی هستن که یه تابع یا کلاس رو به عنوان ورودی می‌گیرن و یه نسخه تغییر یافته برمی‌گردونن. وقتی از علامت @ استفاده می‌کنید، پایتون به طور خودکار این کار رو انجام می‌ده.

🔻 مراحل استفاده از دکوریتور:
تعریف دکوریتور:
دکوریتور یه تابعه که یه تابع ورودی می‌گیره و نسخه بهبود یافته یا تغییر یافته رو برمی‌گردونه.

اعمال دکوریتور:
با قرار دادن علامت @ قبل از تعریف تابع یا کلاس، دکوریتور روی اون اعمال می‌شه.

اجرای تابع دکوریتور:
وقتی تابع دکوریت شده فراخوانی می‌شه، اول تابع "بسته‌بندی" (wrapper) اجرا می‌شه و بعد تابع اصلی.

🔻 مثال دکوریتور بر روی کلاس
دکوریتورها فقط برای توابع نیستن؛ می‌تونن رفتار کلاس‌ها رو هم تغییر بدن. مثلاً:
def add_str(cls):
# افزودن یه متد برای نمایش
def __str__(self):
return f"{cls.__name__} با ویژگی‌ها: {self.__dict__}"
cls.__str__ = __str__
return cls

@add_str
class Person:
def __init__(self, name, age):
self.name = name
self.age = age

p = Person("سارا", 28)
print(p) # خروجی: Person با ویژگی‌ها: {'name': 'سارا', 'age': 28}

اینجا دکوریتور add_str متد str
رو به کلاس Person اضافه می‌کنه، بدون اینکه کد داخل کلاس رو تغییر بده.

3⃣ مزایای استفاده از دکوریتورها
کنترل دقیق روی ساختار کد:
دکوریتورها به شما این امکان رو می‌دن تا بدون دست زدن به منطق اصلی تابع یا کلاس، رفتارشون رو تغییر بدید. این موضوع برای توسعه چارچوب‌های پیچیده خیلی مفیده.

اجرای الگوهای تکراری (DRY):
می‌تونید کدهای تکراری مثل ثبت رویدادها، اعتبارسنجی یا مدیریت استثناها رو توی یه مکان متمرکز کنید.

گسترش قابلیت‌ها:
به راحتی می‌شه قابلیت‌های جدیدی به توابع یا کلاس‌ها اضافه کرد بدون اینکه لازم باشه کد اصلی رو تغییر بدید.

4⃣ چالش‌های استفاده از دکوریتورها ⚠️
درک اولیه سخت‌تر:
برای کسانی که تازه شروع کردن، مفهوم دکوریتورها ممکنه گیج‌کننده باشه. برای درک کاملش نیاز به مطالعه و تمرین داره.

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

ترکیب با سایر مفاهیم:
استفاده همزمان از دکوریتورها با مفاهیم پیشرفته مثل متاکلاس‌ها یا توابع بازگشتی می‌تونه باعث پیچیدگی‌های اضافه بشه.

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

#⃣ #python #programming



🥷 CHANNEL | GROUP
14👍6👌2
خب خب خب پشت صحنه دکوریتورها در پایتون: چه اتفاقی پشت پرده می‌افته؟ 🚀

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

1⃣ پایتون چطوری کد رو اجرا می‌کنه؟ 📜
قبل از اینکه بریم سراغ دکوریتورها، یه نکته مهم:
پایتون یه زبان مفسریه، یعنی خط‌به‌خط کد رو اجرا می‌کنه. ولی قبل از اجرا، اول کد رو به بایت‌کد تبدیل می‌کنه و بعد اون رو می‌فرسته برای ماشین مجازی پایتون (PVM).
تو این فرآیند، هر تابع و کلاس یه آبجکت جداگانه توی حافظه می‌شه و همینجاست که دکوریتورها وارد عمل می‌شن 🚀

2⃣ دکوریتورها دقیقاً چیکار می‌کنن؟ 🔧

1⃣ وقتی @ می‌ذاریم، واقعاً چی می‌شه؟
وقتی یه تابع رو با @my_decorator دکوریت می‌کنیم، پایتون پشت صحنه این کارو انجام می‌ده:
@my_decorator
def func(...):
...

میشه این:
def func(...):
...

func = my_decorator(func)

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

2⃣ ترتیب اجرا چطوریه؟
وقتی دکوریتور روی تابع اعمال می‌شه:
تابع اصلی به عنوان یه آبجکت ساخته می‌شه.

دکوریتور اجرا می‌شه و تابع اصلی رو می‌گیره.

خروجی دکوریتور جایگزین تابع اصلی می‌شه.

پس، از این به بعد هر وقت تابع رو صدا بزنید، در واقع دارید خروجی دکوریتور رو اجرا می‌کنید، نه تابع اصلی رو

3⃣ چه بلایی سر تابع میاد؟ 🔍

1⃣ تابع اصلی تبدیل می‌شه به...
هر تابع تو پایتون یه آبجکته، پس دکوریتورها می‌تونن روش تغییرات زیادی بدن:
قبل از اجرا یه کار انجام بدن (مثلاً لاگ بگیرن).
تابع اصلی رو اجرا کنن.
بعد از اجرا هم یه کار دیگه انجام بدن (مثلاً خروجی رو دستکاری کنن).
یا حتی یه چیز کاملاً جدید برگردونن
در نتیجه، اسم تابع دیگه به اون چیزی که اول تعریف کردید اشاره نمی‌کنه، بلکه به خروجی دکوریتور اشاره داره.

2⃣ مشکل متادیتا و راه‌حل functools.wraps
یه مشکل اینه که دکوریتور باعث می‌شه اطلاعات تابع (مثل نام، توضیحات و...) از بین بره. برای حل این مشکل، باید از functools.wraps استفاده کنیم:
import functools

def log_calls(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print(f"قبل از اجرای {func.__name__}")
result = func(*args, **kwargs)
print(f"بعد از اجرای {func.__name__}")
return result
return wrapper

اینطوری، متادیتای تابع اصلی حفظ می‌شه وdoc __doc__ دسترسی داشت. 😎

3⃣ دکوریتورهای پشت سر هم (Chaining Decorators)
اگه چندتا دکوریتور رو روی یه تابع بذاریم، ترتیبش مهمه. به این مثال دقت کن:
@decorator_a
@decorator_b
def func():
pass

اول decorator_b اجرا می‌شه و خروجی‌ش می‌ره تو decorator_a. پس ترتیب اجرا به این شکله:
func = decorator_b(func)

func = decorator_a(func)


پس، دکوریتوری که پایین‌تر نوشته شده، زودتر اجرا می‌شه 🔄

4⃣ پشت صحنه در زمان کامپایل و اجرا 🕒

1⃣ دکوریتور کی اجرا می‌شه؟
دکوریتورها همون موقعی که تابع یا کلاس تعریف می‌شه اجرا می‌شن، نه وقتی که تابع رو صدا می‌زنید. پس این کد:
@my_decorator
def my_func():
pass

در لحظه‌ای که پایتون به این خط کد می‌رسه، my_decorator(my_func) اجرا می‌شه و خروجی‌ش جایگزین my_func می‌شه.

2⃣ ذخیره تابع در فضای نام (Namespace Binding)
بعد از این فرآیند، اسم تابع به تابع دکوریت‌شده اشاره می‌کنه. پس اگه تابع اصلی رو نگه نداشته باشید، دیگه بهش دسترسی ندارید

3⃣ تأثیر روی بهینه‌سازی
چون دکوریتورها می‌تونن کد تابع رو تغییر بدن، ممکنه باعث بشن که بهینه‌سازی‌هایی که پایتون انجام می‌ده، دیگه درست کار نکنه. برای مثال، اگه دکوریتور یه حلقه اضافه کنه یا اجرای تابع رو تغییر بده، بایت‌کد نهایی کاملاً متفاوت می‌شه.

5⃣ نکات مهم که باید رعایت کنید 💡

از functools.wraps استفاده کنید
اگه دکوریتورتون متادیتای تابع رو تغییر می‌ده، این کار باعث می‌شه اطلاعات تابع اصلی حفظ بشه.

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

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

#⃣ #python #programming



🥷 CHANNEL | GROUP
14👍6🔥3👎1👏1👌1
خب خب خب جلوگیری از Race Condition در جنگو با select_for_update 🔒🚀

توی این پست در مورد Race Condition صحبت کردیم و گفتیم چطور ممکنه چندتا درخواست همزمان بیان و دیتا رو خراب کنن. حالا بریم ببینیم جنگو چه ترفندهایی برای کنترل این مشکل داره و چطور می‌تونیم از select_for_update استفاده کنیم.

مشکل چیه؟ 🤔
فرض کن یه سیستم بانکی داری و کاربرا دارن پول جابه‌جا می‌کنن. حالا دو نفر همزمان می‌خوان از حسابشون پول بردارن و موجودی حساب فقط 100 تومنه. اگه این درخواست‌ها بدون قفل کردن دیتا پردازش بشن، ممکنه هر دو برداشت موفق بشن و سیستم بدهکار بشه 😬
اینجا همون جاییه که select_for_update میاد وسط و دیتا رو از فاجعه نجات می‌ده.


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

مثال 1: جلوگیری از برداشت همزمان از حساب بانکی 🏦
from django.db import transaction
from myapp.models import Account

def withdraw_money(account_id, amount):
with transaction.atomic(): # شروع تراکنش
account = Account.objects.select_for_update().get(pk=account_id) # قفل کردن رکورد
if account.balance >= amount:
account.balance -= amount
account.save()
print("برداشت موفقیت‌آمیز بود!")
else:
print("موجودی کافی نیست!") # جلوگیری از برداشت بیش از حد

این کد مطمئن می‌شه که وقتی یه درخواست داره موجودی رو چک می‌کنه و کم می‌کنه، هیچ درخواست دیگه‌ای همزمان وارد عمل نشه.

مثال 2: انتقال وجه بین دو حساب 💳
حالا یه چالش سخت‌تر انتقال پول از یه حساب به حساب دیگه. باید هر دو حساب همزمان قفل بشن تا مشکلات همزمانی پیش نیاد.
from django.db import transaction
from myapp.models import Account

def transfer_money(from_id, to_id, amount):
with transaction.atomic():
accounts = Account.objects.select_for_update().filter(pk__in=[from_id, to_id]).order_by("id")

sender = accounts[0]
receiver = accounts[1]

if sender.balance >= amount:
sender.balance -= amount
receiver.balance += amount
sender.save()
receiver.save()
print("انتقال وجه موفقیت‌آمیز بود!")
else:
print("موجودی کافی نیست!") # جلوگیری از انتقال اشتباه

اینجا هر دو حساب رو قفل می‌کنیم تا حتی اگه دو درخواست انتقال پول به صورت همزمان بیاد، هیچکدوم نتونن وسط کار رو همدیگه تأثیر بذارن.

چندتا نکته 🚀

🔹 انتخاب نوع قفل (select_for_update(nowait=True))
اگه بخوای درخواست‌های معطل رو سریع رد کنی، می‌تونی nowait=True بذاری که اگه رکورد قفل بود، درخواست جدید منتظر نمونه و مستقیم خطا بده.
account = Account.objects.select_for_update(nowait=True).get(pk=1)

☝️ این باعث می‌شه که اگه رکورد قفل باشه، جنگو بلافاصله یه DatabaseError بده و منتظر نمونه.

🔹 قفل کردن رکوردها بدون مسدود کردن خواندن (select_for_update(skip_locked=True))
اگه درخواست‌های زیادی داری و نمی‌خوای که یک درخواست کل سیستم رو بلاک کنه، می‌تونی از skip_locked=True استفاده کنی که درخواست‌های دیگه بتونن رکوردهای آزاد رو پردازش کنن.
account = Account.objects.select_for_update(skip_locked=True).get(pk=1)

☝️ این کار باعث می‌شه که اگه یه رکورد قفل بود، درخواست بیخیال اون رکورد بشه و فقط رکوردهایی که قفل نیستن رو انتخاب کنه.

🔹 مدیریت تایم‌اوت قفل (set statement_timeout)
اگه نمی‌خوای که درخواست‌ها مدت زیادی بلاک بشن، توی PostgreSQL می‌تونی یه تایم‌اوت برای قفل تعیین کنی:
SET statement_timeout = '5s'; 

☝️ این یعنی اگه یه درخواست بیشتر از ۵ ثانیه قفل بمونه، بهش خطا داده می‌شه و می‌ره بیرون.

جمع‌بندی
select_for_update یکی از قوی‌ترین ابزارها برای جلوگیری از Race Condition توی جنگوئه. مهم‌ترین نکاتش اینان:
قفل کردن رکوردهای دیتابیس موقع آپدیت برای جلوگیری از دستکاری همزمان
استفاده از nowait=True برای جلوگیری از انتظار بیش از حد
استفاده از skip_locked=True برای رد کردن رکوردهای قفل‌شده و ادامه پردازش.


#️⃣ #python #programming #db



🥷 CHANNEL | GROUP
1👍20🔥42👌1
خب خب خب WebSocket در Fastapi 🌀

امروز می‌خوام درباره‌ی یه موضوع باحال و کاربردی تو دنیای وب حرف بزنم: پیاده‌سازی WebSocket در FastAPI اگه دنبال ساخت اپلیکیشن‌های realtime مثل چت، داشبوردهای زنده یا بازی‌های آنلاین هستین، این پست براتون خیلی مفیده. پس با من همراه باشین تا با هم یاد بگیریم WebSocket چیه و چطور می‌تونیم تو FastAPI ازش استفاده کنیم.

🧠 WebSocket چیه و چرا مهمه؟
‏ WebSocket یه پروتکل ارتباطیه که به کلاینت (مثل مرورگر) و سرور اجازه می‌ده یه ارتباط دوطرفه و همیشگی داشته باشن. برعکس HTTP که فقط یه درخواست می‌فرستی و یه پاسخ می‌گیری، WebSocket این امکان رو می‌ده که هر دو طرف هر وقت خواستن پیام بفرستن و بگیرن، بدون اینکه نیاز باشه کلاینت مدام درخواست بفرسته. این برای اپلیکیشن‌هایی که نیاز به آپدیت‌های زنده دارن، مثل چت روم‌ها، اعلان‌های realtime یا بازی‌های آنلاین، عالیه

🚀 FastAPI و WebSocket

FastAPI یه فریم‌ورک وب مدرن و سریع برای پایتونه. یکی از قابلیت‌های باحالش هم پشتیبانی از WebSocketه. FastAPI از Starlette استفاده می‌کنه (یه فریم‌ورک ASGI سبک و قدرتمند)، و همین باعث می‌شه بتونیم به راحتی WebSocket رو پیاده‌سازی کنیم.

🛠 چطوری WebSocket رو تو FastAPI پیاده‌سازی کنیم؟

برای شروع، باید از کلاس WebSocket تو FastAPI استفاده کنیم. بیاین با یه مثال ساده شروع کنیم:
from fastapi import FastAPI, WebSocket

app = FastAPI()

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
while True:
data = await websocket.receive_text()
await websocket.send_text(f"پیامت این بود: {data}")

تو این کد:
یه endpoint به اسم /ws ساختیم.

وقتی کلاینت بهش وصل می‌شه، سرور با accept() ارتباط رو قبول می‌کنه.

بعدش تو یه حلقه پیام‌های کلاینت رو می‌گیره و همونو برمی‌گردونه.


به این می‌گن یه Echo Server ساده هر چی کلاینت بفرسته، سرور عینشو برمی‌گردونه.

📡 یه مثال پیشرفته‌تر: چت روم با WebSocket

حالا بیاین یه چیز باحال‌تر بسازیم، مثلاً یه چت روم که چندتا کلاینت بتونن بهش وصل بشن و پیام‌هاشون رو به هم بفرستن. برای این کار، باید اتصال‌های فعال رو مدیریت کنیم. یه کلاس به اسم ConnectionManager می‌سازیم که لیست اتصال‌ها رو نگه داره و بتونیم بهشون پیام بفرستیم یا به همه broadcast کنیم.
from fastapi import FastAPI, WebSocket
from typing import List

app = FastAPI()

class ConnectionManager:
def __init__(self):
self.active_connections: List[WebSocket] = []

async def connect(self, websocket: WebSocket):
await websocket.accept()
self.active_connections.append(websocket)

def disconnect(self, websocket: WebSocket):
self.active_connections.remove(websocket)

async def send_personal_message(self, message: str, websocket: WebSocket):
await websocket.send_text(message)

async def broadcast(self, message: str):
for connection in self.active_connections:
await connection.send_text(message)

manager = ConnectionManager()

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await manager.connect(websocket)
try:
while True:
data = await websocket.receive_text()
await manager.send_personal_message(f"تو نوشتی: {data}", websocket)
await manager.broadcast(f"یکی گفت: {data}")
except Exception as e:
print(f"خطا: {e}")
finally:
manager.disconnect(websocket)

اینجا چی داریم؟
‏ConnectionManager یه کلاسه که اتصال‌های فعال رو تو یه لیست نگه می‌داره.
وقتی کلاینت وصل می‌شه، به لیست اضافه می‌شه (connect) و وقتی قطع می‌شه، حذف می‌شه (disconnect).

‏send_personal_message به یه کلاینت خاص پیام می‌فرسته.

‏broadcast به همه کلاینت‌های وصل‌شده پیام رو می‌فرسته.

تو endpoint، پیام کلاینت رو می‌گیریم، به خودش یه جواب شخصی می‌دیم و به بقیه هم broadcast می‌کنیم.

جمع‌بندی

‏WebSocket تو FastAPI به شما این امکان رو می‌ده که اپلیکیشن‌های realtime و جذاب بسازین. از چت روم‌ها گرفته تا داشبوردهای زنده و بازی‌های آنلاین.

خب اینم از این امید وارم مفید بوده باشه :]

#️⃣  #fastapi #backend #python


🥷 CHANNEL | GROUP
👍11👌53🔥2👏1🤩1
آیا پایتون همیشه کنده؟ 🐢

چیزی که همیشه از زبون همه ی برنامه نویسا می‌شنویم (مخصوصا جامعه محترم C#) اینه که پایتون خیلی کنده (نسبت به زبان های دیگه هرچند این مقایسه اشتباهه بعضی جاها)
خب اره، درسته پایتون کنده (البته در حالت pure)
توی این پست میخوام بگم که چرا کنده و چجوری میشه سریعش کرد؟

چرا پایتون کنده ؟ 🤓

همونجور که میدونید پایتون به صورت پیش‌فرض با CPython اجرا می‌شه، که یه مفسر (interpreter) برای پایتونه و با زبان C نوشته شده. CPython کد پایتون رو به بایت‌کد (bytecode) تبدیل می‌کنه و بعد اون رو تو یه ماشین مجازی (VM) اجرا می‌کنه. این فرایند باعث می‌شه پایتون نسبت به زبان‌های کامپایل‌شده مثل C یا Rust کندتر باشه، چون
تفسیر خط‌به‌خط انجام میده و به جای کامپایل مستقیم به کد ماشین، پایتون تو زمان اجرا تفسیر می‌شه.
GIL (Global Interpreter Lock) تو CPython، یه قفل سراسری هست که جلوی اجرای چند نخ (thread) همزمان رو می‌گیره و برای کارهای multithreading مشکل‌ساز می‌شه.
داینامیک تایپ بودن پایتون تایپ‌ها رو تو زمان اجرا چک می‌کنه، که یه کم سرعت رو پایین میاره.

ولی خبر خوب اینه که پایتون راه ها و ابزارهایی داره که می‌تونن این کندی رو برطرف کنن و پرفورمنس رو حسابی بالا ببرن

راه ها و ابزارهایی برای افزایش سرعت 📚

1️⃣ PyPy 🌟
‏Pypy یه مفسر جایگزین برای پایتونه که از JIT (Just-In-Time Compilation) استفاده می‌کنه.
و کارکردش اینجوریه که کد پایتون رو به جای تفسیر ساده، تو زمان اجرا به کد ماشین کامپایل می‌کنه. این یعنی برای حلقه‌ها و عملیات تکراری خیلی سریع‌تره.
مزیتشم اینه تو بعضی موارد تا ۷ برابر سریع‌تر از CPython عمل می‌کنه
و باید توجه داشت باشید برای کدهایی که با C extensionها (مثل NumPy) کار می‌کنن، کامل سازگار نیست.

2️⃣ Cython
‏Cython یه ابزار که کد پایتون رو به C تبدیل می‌کنه و بعد کامپایلش می‌کنه.
اینجوری کار میکنه که می‌تونی تایپ‌های استاتیک (مثل int یا float) به متغیرها‏ اضافه کنی تا سرعتش بیشتر بشه. بعد Cython این کد رو به C تبدیل می‌کنه و یه فایل باینری سریع تحویلت می‌ده.
و تا چندین برابر سریع‌تر از CPython می‌شه، به‌خصوص برای محاسبات سنگین.

3️⃣ Numba 🔥
‏Numba یه کامپایلر JIT برای پایتونه که با دکوریتور @jit کار می‌کنه.
کارکردش اینجوریه که کد پایتون رو تو زمان اجرا به کد ماشین تبدیل می‌کنه، بدون نیاز به تغییر زیاد تو کدنویسی.
برای حلقه‌ها و محاسبات عددی (مثل کار با آرایه‌ها) تا ۱۰۰ برابر سریع‌تر می‌شه

4️⃣ CPython با C Extensions 🛠️
می‌تونی بخش‌های کند پروژت یا جاهایی که به سرعت بالا نیاز داری رو با C بنویسی و به CPython وصل کنی.
اینجوریه که کد C رو به صورت ماژول می‌سازی و تو پایتون لودش می‌کنی.
و سرعت C رو با سادگی پایتون ترکیب می‌کنی. کتابخونه‌هایی مثل NumPy و Pandas از این روش استفاده می‌کنن.

و در اخر پایتون همیشه کند نیست 🙃

حقیقت اینه که پایتون به تنهایی برای خیلی از کارها به اندازه کافی سریعه، به‌خصوص تو پروژه‌هایی که I/O (مثل شبکه یا دیتابیس) گلوگاه اصلیه، نه CPU. ولی وقتی پای محاسبات سنگین وسط میاد، ابزارهایی مثل PyPy، Cython و Numba می‌تونن پرفورمنس رو چند برابر کنن. مثلاً:
یه حلقه ساده با Numba می‌تونه از ۵ ثانیه به ۰.۰۵ ثانیه برسه
‏PyPy تو برنامه‌های واقعی تا ۷ برابر سرعت رو بالا برده. 🐆

#️⃣ #python


🥷 CHANNEL | GROUP
👌93👍2🔥2
خب خب آپدیت جدید جنگو اینجاست، ببینیم چه تغییراتی داشته🔥🛠
چند روز پیش (۲ آوریل) آپدیت جدید جنگو با ورژن ۵.۲ منتشر شد. این نسخه LTS هست و تا آوریل ۲۰۲۸ پشتیبانی میشه. توی این نسخه تغییرات بیشتر مربوط به زیرساخت هایی مثل دیتابیس و shell جنگو بودن. بریم بررسیشون کنیم.

1️⃣ ایمپورت خودکار مدل ها توی shell
از این نسخه به بعد وقتی وارد shell جنگو میشین مدل هاتون به صورت خودکار ایمپورت میشن. این ویژگی بهتون کمک میکنه که زمان کمتری برای ایمپورت کردن بزارین و باعث صرفه جویی در زمان میشه.

2️⃣ پشتیبانی از کلید اصلی مرکب(Composite Primary Key)

با اضافه شدن CompositePrimaryKey، میتونین چند فیلد رو به عنوان کلید اصلی مشخص کنید. قبلا این کار نیاز به تنظیمات دستی توی سطح دیتابیس داشت اما الان به صورت رسمی پشتیبانی میشه و مدیریتش ساده تره.

3️⃣ ساده تر شدن شخصی سازی BoundField
توی این نسخه میتونید کلاس BoundField رو به راحتی توی سطح پروژه یا فرم شخصی سازی کنید. با ایجاد یک کلاس که از BoundField ارث بری میکنه و اعمال تغییرات مورد نظر میتونید اون رو به فیلد های فرم هاتون اختصاص بدین.
‏BoundField همون چیزیه که وقتی توی قالب می‌نویسید form.name، پشت صحنه وظیفه داره اون فیلد رو به HTML تبدیل کنه، مقدارش رو بذاره، ارورهاش رو نشون بده و...
یجورایی رابط بین فرم و فیلد واقعی‌ توی قالبه.


4️⃣ فیلتر های Facet توی پنل ادمین
توی پنل ادمین جنگو، با فعالسازی ویژگی ModelAdmin.show_facets، میتونید تعداد آیتم های توی هر فیلتر رو ببینید. این قابلیت باعث میشه اطلاعات پنل ادمین رو راحت تر مدیریت کنید.

5️⃣ فیلد های تولید شده(Generated Fields)

با معرفی GeneratedFields، میتونید فیلد هایی تعریف کنید که مقدارشون بر اساس مقدار سایر فیلد های مدل محاسبه و ثبت میشه. این ویژگی بهتون این امکان رو میده که ستون های محاسبه شده توی دیتابیس قرار بدین.

6️⃣ مقادیر پیش فرض در سطح دیتابیس

با استفاده از پارامتر db_default توی فیلد های مدل، مقادیر پیش فرض مستقیما توسط دیتابیس اعمال میشن. این ویژگی باعث بهبود عملکرد و سازگاری بیشتر با دیتابیس های مختلف میشه.

⏺️ با استفاده از لینک زیر میتونید اطلاعات بیشتری درمورد این آپدیت کسب کنید⚡️

Django 5.2 release notes

#django #backend #python


🥷🏻 CHANNEL | GROUP
16👍3
خب خب خب، کامند inspectdb توی جنگو⚙️
احتمالا به این فکر کردین که چطوری میشه از جدول های یه دیتابیس آماده توی جنگو استفاده کرد. راه حلش این ابزاره.

‏inspectdb چیه
؟
با استفاده از inspectdb، جنگو میتونه ساختار جدول های دیتابیس رو بررسی کنه و یه فایل مدل جنگو(مثل model.py) تولید کنه و توی خروجی نمایش بده. این یعنی دیگه نیاز نیست برای دیتبایس قدیمیتون دستی مدل بنویسید، جنگو اینکارو هم خودش انجام میده.
python manage.py inspectdb > models.py

شما حتی میتونید فقط یه جدول رو بررسی و تبدیل کنید:
python manage.py inspectdb my_table > models.py


این ابزار میتونه توی این مواقع کمکتون کنه:
1️⃣ وقتی روی یه دیتابیس قدیمی یا پروژه ی legacy کار میکنید.
2️⃣ موقع مهاجرت از یه سیستم دیگه به جنگو.
3️⃣ وقتی میخوان بدون نوشتن کلی کد دستی با یه دیتابیس خارجی کار کنید.

نکته مهم⚠️:
کدی که این ابزار تولید میکنه همیشه تمیز و ایده‌آل نیست. بهتره بعد از ساخت، مدل‌ها رو یه دور بازبینی و شخصی‌سازی کنید. جنگو خودش هم توی فایل تولید شده این هشدار رو مینویسه.


⏺️ برای اطلاعات بیشتر میتونید به داکیومنت جنگو مراجعه کنید:
inspectdb در جنگو

#⃣ #django #python #db


🥷🏻 CHANNEL | GROUP
👍15
سیستم مدیریت وابستگی در FastAPI
یکی از بهترین ویژگی های FastAPI، سیستم مدیریت وابستگی(Dependnecy Injection) اون هست، این سیستم باعث میشه کد ما تمیز تر، تست پذیر تر و قابل توسعه تر بشه.
بهتره برای درک بهتر این پست درمورد Dependency Injectionرو مطالعه کنید تا با پایه و اساس این مبحث آشنا بشین.

‏Depends چیه؟
این کلاس توی FastAPI، برای مدیریت وابستگی ها استفاده میشه. به زبان ساده Depends یه راهه که بتونیم بک تابع یا آبجکت رو به صورت خودکار به فانکشن های دیگه تزریق کنیم بدون اینکه دستی اونارو صدا بزنیم یا بخونیم.
با یه مثال ساده شروع میکنیم:
from fastapi import FastAPI, Depends

app = FastAPI()

def get_db():
db = "Database Connection"
try:
yield db
finally:
print("Closing DB connection")

@app.get("/items/")
def read_items(db = Depends(get_db)):
return {"db_connection": db}

اینجا read_items خودش مستقیم سشن دیتابیس رو نمیسازه، فقط میگه: من به یه سشن دیتابیس نیاز دارم.
‏FastAPI به صورت خودکار get_db رو صدا میزنه و نتیجه رو به db میده.

چرا این سیستم خوبه؟
وابستگی ها مدیریت شده و قابل کنترل میشن
کد تست پذیر تر میشه
ساختار پروژه ماژولار میشه
لاجیک لایه های مختلف جدا میشه و تغییرات ساده تر میشن

اگه ازش استفاده نکنیم چی؟
خب با استفاده نکردن از این ویژگی یه کمک بزرگ رو از دست میدین. به طور مثال اگه وابستگی ها تو در تو باشن شما میتونید فقط با همین ویژگی کلی به تمیزی کدتون کمک کنید.
from fastapi import Header, HTTPException, APIRouter, Depends


router = APIRouter()

def get_token(token: str = Header(...)):
return token

def get_current_user(token: str = Depends(get_token)):
user = {"username": "abolfazl", "role": "admin"}
return user

def require_admin(user: dict = Depends(get_current_user)):
if user["role"] != "admin":
raise HTTPException(status_code=403, detail="Not authorized")
return user

def list_users_service():
return [{"username": "a"}, {"username": "b"}]

@router.get("/users")
def list_users(admin_user: dict = Depends(require_admin)):
users = list_users_service()
return users

توی مثال بالا میتونید چندین لایه از وابستگی رو ببینید که به خوبی با Depends مدیریت شدن. حالا اگه این سیستم وجود نداشت چی؟
def list_users():
token = get_token()
user = get_current_user(token)
admin_user = require_admin(user)
...

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

پشت صحنه چه اتفاقی میوفته؟

‏FastAPI از بالا شروع کرد به نگاه کردن:
دید require_admin به get_current_user نیاز داره، بعد دید get_current_user هم به get_token نیاز داره، پس اول get_token اجرا شد، بعد get_current_user بعد هم require_admin. هربار خروجی یه فانکشن، ورودی فانکشن بعدی شد. درنهایت اگه مشکلی نباشه میرسیم به endpoint.

از کجا فهمید چی رو به کجا بفرسته؟

خب باید بگم که FastAPI به شدت به تایپ هینت ها وابسته است و خیلی ازشون استفاده میکنه. همین Depends هم با استفاده از تایپ هینت ها جای مقادیر رو درک میکنه. یه فانکشن توی پایین ترین لایه یه آرگومان با تایپ Header داره؟ خب Depends اون آرگومان رو توی درخواست دریافت میکنه به اون فانکشن میرسونه.

کجا ازش استفاده کنیم؟
هر وابستگی ای که نیاز داره یه پارامتری رو مستقیما از درخواست بگیره و روش پردازش انجام بده، و به نحوی قبل از فانکشن endpoint اجرا بشه و نتیجه ی آماده داشته باشه(درست همونطور که گفتم، قبل از بدنه ی اصلی فانکشن) باید با Depends استفاده بشه. مثلا گرفتن توکن از هدر یا چک کردن دسترسی ها، اتصال به دیتابیس

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

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

#️⃣ #fastapi #python #backend


🥷🏻 CHANNEL | GROUP
👍14
🟡 خب خب خب، PEP8: قوانین طلایی برای کدنویسی پایتون
وقتی به برنامه‌نویسی پایتون علاقه‌مند می‌شید، یکی از اولین چیزهایی که باید یاد بگیرید PEP8 هست. این یه استاندارد رسمی برای کدنویسی به زبان پایتونه که توسط Python Software Foundation منتشر شده و هدفش اینه که کدهای پایتون هماهنگ، خوانا و استاندارد باشن. با این استاندارد کد های همه برنامه های پایتون توی مسائل پایه ای استایل کد مثل هم میشه و خوندن و درک کد های مختلف هم ساده تر میشه. توی این پست می‌خوایم توضیح بدیم که PEP8 چیه، چرا مهمه و چندتا از مهم‌ترین قواعدش رو بررسی کنیم.

PEP8 چی هست؟
‏PEP8 یه استاندارد شامل یه سری دستورالعمل ها و قوانین برای نوشتن کد منظم و تمیز پایتونه. این استاندارد برای کمک به برنامه نویس ها تنظیم شده تا کدی بنویسن که هم برای خودشون هم برای دیگران قابل فهم باشه. دستورااعمل های این استاندارد شامل اصولی درمورد قواعد نام گذاری، استایل کد، تو رفتگی ها و ... میشه.

چرا باید از PEP8 استفاده کنیم؟
خوانایی بیشتر: کد هایی که طبق استاندارد های خاصی نوشته میشن، برای دیگران راحت تر قابل فهم هستن.
نگهداری ساده تر: کد استادارد به راحتی قابل تغییر و گسترشه.
هماهنگی بین تیم ها: وقتی همه از یک استاندارد پیروی کنن، حتی اگه جند نفر هم روی یک پروژه کار کنن کار کردن با کد ها خیلی راحت تر میشه

اصول کلیدی PEP8
1️⃣ قواعد نام گذاری(Naming Conventions)
نام گذاری درست متغیر ها، توابع، کلاس ها و ماژول ها باعث میشه کد شما خوانا و قابل فهم باشه.

نام متغیر ها و توابع: از snake_case استفاده کنید.
my_variable = 10
def my_function():
pass

نام کلاس ها: باید از CapCase استفاده کنید
class UserProfile:
pass

نام ماژول ها: میشه از lowercase استفاده کنید و برای جدا کردن کلمات از خط تیره (-) نکنید
import mymodule
import user_routers


2️⃣ چیدمان کد(Code Layout)
چیدمان منظم کد برای راحتی خوندن و نگهداری کد ها ضروریه
طول خط ها:‌ طول خط ها توی پایتون نباید بیشتر از ۷۹ کاراکتر باشه. این باعث میشه که کد های توی ابزارهای مختلف(مثل کامند git diff) و ترمینال راحت تر دیده بشن.
فاصله های خالی: بعد از کاما و آرگومان ها یک فاصله بگذارین:
print("This code is too long and does not follow the standard. It cannot be read. properly in some tools like 'git diff'. This line should be broken into. multiple lines to follow the standard. The maximum length for a line is 79 characters.")

def my_function(x, y):
return x + y


3️⃣ تو رفتگی(Indentation)
تو رفتگی ها برای نمایش ساختار کد و مشخص کردن بلوک های کد استفاده میشن.
از ۴ فضای خالی برای هر سطح تو رفتگی استفاده کنید.
class MyMath:
def my_function(self, x):
if x > 0:
print("Positive")
else:
print("Negative")


5️⃣ فضای خالی در عبارات و دستورات (Whitespaces in Expressions and Statements)

فضای خالی در عبارات و دستورات به خوانایی کد کمک می‌کنه:
قبل و بعد از اپراتورهای ریاضی فاصله بگذارید:
x = 5 + 3

در داخل پرانتزها فاصله نگذارید:
my_function(1, 2, 3)

فاصله هارو فقط قبل از هر کاما بذارید:
a, b, c = 1, 2, 3


چجوری همیشه این قواعد رو رعایت کنیم؟
خب یه راه آسونش میتونه استفاده از ابزار هایی مثل pylint و flake8 باشه. اما یه راه راحت تر، اگه از IDE هایی مثل Pycharm استفاده میکنید خودشون وقتی که کد غیر استاندارد بنویسید بهتون میگن و بییشتر مواقع خودشون کد رو درست میکنن. اگه از VSCode یا هر ادیتور دیگه ای استفاده میکنید میتونید افزونه ی مربوط به این استاندارد رو روش نصب و استفاده کنید.

جمع بندی✍️
‏PEP8 به شما کمک میکنه که کد پایتون تمیز، خوانا و استاندارد بنویسید. رعایت قواعدی مثل نام گذاری درست، استفاده مناسب از فاصله ها و تو رفتگی ها باعث میشه کد شما به راحتی قابل نگهداری و درک باشه.

#️⃣ #programming #python


🥷🏻 CHANNEL | GROUP
👍182
خب خب خب،‌ معرفی Pylint🏛️
اگه با پایتون کار میکنین و میخواین کدتون تمیز باشه، حتما باید با ابزارهایی مثل pylint اشنایی داشته باشین. این ابزار ها میان یک سری قوانین و قواعد ثابت رو براتون تعریف میکنن و بررسی میکنن که توی کدتون این قواعد رعایت شده یا نه.

‏Pylint چیه؟🤔
‏pylint به ابزار linter برای زبان پایتونه که کد رو بررسی میکنه، اشتباهات رایج رو گزارش میده، با استاندارد های PEP8 ارزیابیش میکنه و در نهایت یه امتیاز (از ۰ تا ۱۰) به کدی که نوشتین میده. این ابزار باعث میشه کد هاتون استاندارد و قابل توسعه باشن و میتونه توی رعایت کردن اصول PEP8 بهتون کمک کنه.

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

نصب و استفاده🚀
میتونید با دستور زیر این ابزار رو نصب کنید.
pip install pylint

اجرا روی یه فایل
pylint main.py

یا روی یه پروژه ی کامل
pylint myproject/

خب حتما بعد اجرا متوجه شدین که دیگه خیلی داره سخت میگیره یا اینکه میخواین تنظیمات و استایل خودتون رو بهش بدین، میتونین با استفاده از فلگ های دستور pylint این کار رو انجام بدین. به طور مثال خاموش کردن بعضی اخطار ها:
pylint myfile.py --disable=missing-docstring,invalid-name,too-many-arguments --max-line-length=100


کانفیگ Pylint🛠️
خب تایپ و استفاده از دستور قبلی با یه سری شخصی سازی های دیگه خیلی سخت میشه و تا مرز غیرقابل استفاده بودن میرسه، اینجاست که میتونین از فایل کانفیگ استفاده کنین. استفاده از فایل کانفیگ خیلی مرتب تر و تیم پسند تره.
فایل کانفیگ رو با این دستور ایجاد کنین:
pylint --generate-rcfile > .pylintrc

و بعد میتونید طبق استایل کدنویسی خودتون یا استایل مدنظر تیمتون کانفیگ هارو تغییر بدین:
[MESSAGES CONTROL] # disable selected warnings
disable=
missing-docstring,
# no docstring warning
invalid-name,
# allow any names
too-few-public-methods,
# allow few methods
too-many-arguments
# allow many args

[FORMAT] # formatting rules
max-line-length=100
# max line length

میتونین با مراجعه به صفحه کانفیگ ها از داکیومنت رسمی pylint کانفیگ های بیشتری رو ببینین.

جمع بندی✍️
با استفاده از این ابزار میتونین هماهنگی بی نظیری توی کدهاتون ایجاد کنید و اگه توی تیم کار میکنین باعث میشه کل تیم یک سری قواعد و اصول یکپارچه رو رعایت کنن و کد کلی ساختار مشخصی داشته باشه.🏗️ میتونین Pylint رو به IDE ای که استفاده میکنین اضافه کنین تا استفاده ازش ساده تر بشه.

#️⃣ #programming #python


🥷🏻 CHANNEL | GROUP
👍131
خب خب خب، ‏Middleware های FastAPI🚀
خب middleware یه کد واسط بین دریافت درخواست و پاسخ دادن توی یه اپلیکیشن وبه. یعنی هر ریکوئستی که به سرور میرسه، قبل از رسیدن به route اصلی، از middleware رد میشه و همچنین هر درخواستی هم قبل از رسیدن به کلاینت از middleware عبور میکنه تا تغییر داده بشه، لاگ بشه و ...

چطور توی FastAPI ازشون استفاده کنیم؟🤔
‌‏Middleware ها توی FastAPI با دکوریتور app.middleware تعریف میشن و معمولا ساختارشون این شکلیه:
from fastapi import FastAPI, Request

app = FastAPI()

@app.middleware("http")
async def my_middleware(request: Request, call_next):
# Before reaching route
print("Before route")

# Executing View
response = await call_next(request)

# After view did its thing
print("After route")

return response

همونطور که توی مثال بالا دیدید، هر کدی که قبل از اجرای call_next باشه مربوط به درخواست، و هر کدی که بعد از اجرای call_next نوشته بشه مربوط به پاسخ میشه.
توی این مثال قبل از رسیدن درخواست به route اصلی، عبارت 'Before route' چاپ میشه و بعد اینکه route پردازشش با درخواست تموم شد و پاسخ آماده ی برگشت به کلاینت بود، عبارت 'After route' چاپ میشه و بعد از اون پاسخ به کلاینت میرسه.


چندتا مثال ساده برای درک کاربرداش🛠️
از چندتا مثال ساده میتونیم استفاده کنیم
لاگ گیری ساده درخواست ها:
@app.middleware("http")
async def log_requests(request: Request, call_next):
print(f"New request: {request.method} {request.url}")
response = await call_next(request)
return response


اضافه کردن Header به پاسخ:
@app.middleware("http")
async def add_custom_header(request: Request, call_next):
response = await call_next(request)
response.headers["X-App-Version"] = "1.0.0"
return response


سنجش مدت زمان اجرای درخواست:
import time

@app.middleware("http")
async def measure_time(request: Request, call_next):
start = time.time()
response = await call_next(request)
duration = time.time() - start
response.headers["X-Process-Time"] = str(duration)
return response


چندتا نکته📎
1️⃣کلاس Middleware که از FastAPI ایمپورت شده درواقع همون کلاس Middleware توی Starlette هست و برای راحتی میتونیم از FastAPI ایمپورتش کنیم.

2️⃣اگه dependency ای داشته باشیم که با yield تعریف شدن، بخش خرجی اون ها بعد از اجرای middleware اجرا میشه.

3️⃣اگه BackgrounTask ای وجود داشته باشه، اون ها بعد از اجرای همه ی middleware ها اجرا میشن.

جمع بندی✍️
با استفاده از middleware ها میتونید درخواست و پاسخ هارو تمیز کنید، یا قبل از پردازش شدنشون توسط route کارایی که میخواین رو انجام بدین. درواقع با تعریف middleware یه تابع بین client و route اصلی قرار میدیم.

#️⃣ #fastapi #python #backend


🥷🏻 CHANNEL | GROUP
14
خب خب خب، تسک های CPU Bound🔧
احتمالا CPU Bound به گوشتون خورده، همون تسک هایی که بار پردازشی سنگینی دارن. یعنی دیگه منتظر عملیات I/O(خوندن از فایل یا دیتابیس، API خارجی و...) نیستن و عملا انجام شدنشون توسط CPU طول میکشه.

‏CPU Bound
🧮
خب وقتی که به صورت عادی برناممون رو توسعه میدیم، برنامه ی ما فقط توی یک Process و یک هسته ی CPU اجرا میشه. اگه برنامه کار سنگینی مثل پردازش تصویر، محاسبات ریاضی فوق سنگین، الگوریتم های رمزنگاری و فشرده سازی و... داشته باشه، نتیجه اجرا شدنش توی یک Process چیزی بجز کندی و فشار روی CPU نیست. برای مثال شما یه CPU با ۸ هسته دارید ولی برنامه ای که نوشتید فقط روی یک هسته اجرا میشه.
توی این موقعیت میتونیم از Multi Processing استفاده کنیم.

‏Multi Processing یعنی چی؟
🧐
میتونیم با استفاده از Multi Processing برنامه ای که نوشتیم رو توی چند Process و روی چند هسته اجرا کنیم. اینجوری از تمام توان CPU استفاده میشه و در نتیجه هم برنامه ما سریع تر میشه و هم فشار روی هسته های CPU تقسیم میشه.

چرا Multi Threading مناسب نیست؟
💈
توی پایتون برای تسک های CPU ‌‌‌Bound نمیتونیم از Multi Threading استفاده کنیم. چون پایتون یه چیزی به اسم GIL داره که باعث میشه فقط یک Thread بتونه در لحظه اجرا بشه.
یعنی اگه برای تسک های CPU Bound ازش استفاده کنیم در عمل فقط یک Thread داره واقعا اجرا میشه.

استفاده از Multi Processing
🛠
با استفاده از ماژول multiprocessing میتونیم از محدودیت GIL عبور کنیم و چند process داشته باشیم.
یه مثال ساده:
from multiprocessing import Process

def cpu_bound_task():
# مثلاً محاسبه‌ی یک عدد بزرگ
total = 0
for i in range(10**7):
total += i
print(total)

if __name__ == '__main__':
processes = []
for _ in range(4):
p = Process(target=cpu_bound_task)
p.start()
processes.append(p)

for p in processes:
p.join()

این کد تابع cpu_bound_task رو همزمان توی ۴ تا process اجرا میکنه. هر process حافظه، thread و هسته ی CPU خودش رو داره. با اینکار میتونیم واقعا تسک های CPU Bound رو موازی اجرا کنیم و از مزایایی مثل سرعت بهتر بهره مند شیم.
اگه پروژتون بزرگه بهتره تسک های سنگین رو به سیستم هایی مثل Celery بسپرین و از worker های process-based استفاده کنید.

جمع بندی✍️
در نهایت، وقتی با برنامه‌ای سروکار داریم که CPU-bound هست، خیلی مهمه که درست تشخیص بدیم چه راه‌حلی برای بهینه‌سازی استفاده از منابع لازم داریم. توی پایتون، وقتی از multi threading استفاده می‌کنیم، به دلیل محدودیت GIL، همه‌ی پردازش‌ها روی یه هسته و یه thread اجرا می‌شن.
برای این‌که بتونیم از چند هسته‌ی CPU استفاده کنیم و پردازش‌های سنگین رو سریع‌تر انجام بدیم، باید از multi processing بهره بگیریم. با این روش، می‌تونیم هر بخش از برنامه رو به یک process جداگانه اختصاص بدیم که به طور مستقل و هم‌زمان روی هسته‌های مختلف CPU اجرا بشه.

#️⃣ #programmin #python


🥷🏻 CHANNEL | GROUP
👍102
خب خب خب، ‏Background Task ها توی FastAPI🚀
گاهی اوقات نیاز داریم که یه کاری بعد از ارسال پاسخ به کاربر انجام بشه. مثل ارسال ایمیل خوشامد گویی، ثبت لاگ یا آمار توی دیتابیس، پردازش فایل آپلود شده و .... توی این شرایط میتونیم از Background Task ها استفاده کنیم، اینجوری میتونیم بدون معطل کردن کاربر اون کارهارو جداگانه انجام بدیم.

استفاده از Background Task ها🛠
خب اول باید کلاس BackgroundTasks رو ایمپورت کنیم و یه پارامتر از همین نوع برای فانکشن route بنویسیم.
from fastapi import BackgroundTasks, FastAPI

app = FastAPI()


def write_notification(email: str, message=""):
with open("log.txt", mode="w") as email_file:
content = f"notification for {email}: {message}"
email_file.write(content)


@app.post("/send-notification/{email}")
async def send_notification(email: str, background_tasks: BackgroundTasks):
background_tasks.add_task(write_notification, email, message="some notification")
return {"message": "Notification sent in the background"}

حالا FastAPI میاد یه آبجکت با نوع BackgroundTasks برامون ایجاد میکنه و به اون پارامتر پاس میده.
بعد از اینکه فانکشن تسکمون رو ایجاد کردیم میتونیم با استفاده از متود ()add_task از همون پارامتر اون فانکشن رو به صف اجرا اضافه کنیم. همچنین میتونیم آرگومان های مورد نیازمون رو هم با استفاده از همین متود به تسکمون پاس بدیم.

‏Background Tasks و Dependency injection💉
‏Background Tasks به خوبی با سیستم تزریق وابستگی FastAPI سازگاره. میتونیم توی سطح های مختلف برنامه(فانکشن route، یه وابستگی و...) از Background Task استفاده کنیم.
from typing import Annotated

from fastapi import BackgroundTasks, Depends, FastAPI

app = FastAPI()


def write_log(message: str):
with open("log.txt", mode="a") as log:
log.write(message)


def get_query(background_tasks: BackgroundTasks, q: str | None = None):
if q:
message = f"found query: {q}\n"
background_tasks.add_task(write_log, message)
return q


@app.post("/send-notification/{email}")
async def send_notification(
email: str, background_tasks: BackgroundTasks, q: Annotated[str, Depends(get_query)]
):
message = f"message to {email}\n"
background_tasks.add_task(write_log, message)
return {"message": "Message sent"}

توی این مثال بعد از اینکه پاسخ به کلاینت ارسال شد، یه تسک میاد ایمیل کاربر رو توی فایل log.txt مینویسه. اگه یه کوئری پارامتر هم به API ارسال بشه یه تسک دیگه اون رو هم توی فایل مینویسه.

نکته مهم⚠️
این ابزار فقط برای کارهای سبک وسریع مناسبه. مثل همین لاگ نوشتن، ارسال ایمیل یا پردازش های خیلی کوچیک و سبک. برای کارهای سنگین تر مثل پردازش تصویر بهتره که از سیستم هایی مثل Celery استفاده بشه.

جمع بندی✍️
‏Background Task یه ابزار ساده ولی کاربردیه. میتونه توی پروژه هایی که تسک های سنگینی ندارن از Celery بی نیازتون کنه و کارهارو بعد از پاسخ دهی به صورت غیرهمزمان انجام بده.

#️⃣ #fastapi #python #backend


🥷🏻 CHANNEL | GROUP
👍116
خب خب خب، مدیریت تنظیمات با Pydantic⚙️
احتمالا اسم Pydantic به گوشتون خورده یا توی پروژه هاتون ازش استفاده کردین. ولی برای مدیریت تنظیمات پروژه از چی استفاده کردین؟ Pydantic یه کلاس به اسم BaseSettings ارائه میده که برای مدیریت تنظیمات برنامه از جمله متغیر های محیطی و پیش فرض ها استفاده میشه.

چرا از BaseSettings استفاده کنیم؟
🧐
1️⃣ خواندن خودکار متغیر های محیطی:
با استفاده از BaseSettigns بدون نیاز به کتابخونه های اضافی مثل python-dotenv میتونیم به متغیر های محیطی دسترسی داشته باشیم.

2️⃣ اعتبارسنجی امن و خودکار متغیر ها:
‏Pydantic به صورت خودکار تایپ هارو چک میکنه و دیگه نیازی به type cast دستی نیست.

3️⃣ پشتیبانی ساده از چند محیط:
با یکم خلاقیت می‌تونیم چندین کلاس تنظیمات برای محیط‌های مختلف مثل Dev, Prod و Test بسازیم.

4️⃣ مناسب برای پروژه‌های بزرگ:
میشه همه‌ی تنظیمات پروژه مثل دیتابیس، کلیدهای API، حالت دیباگ و... رو توی یک کلاس متمرکز نگهداری کرد و راحت تو کل پروژه استفاده‌شون کرد.

ساختار پایه ی کلاس تنظیمات
🔧
قبل از هر کاری مطمئن بشید که pydantic و پکیج pydantic-settings نصب باشن:
pip install pydantic pydantic-settings

و بعد میتونید با تعریف کلاس و تنظیماتی که نیاز دارین اونارو مدیریت کنین.
from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict

class Settings(BaseSettings):
model_config = SettingsConfigDict(
env_file='.env', # env file location
)
debug: bool = True
database_url: str
secret_key: str

این یعنی:
مقدار debug به طور پیش فرض True هست و بقیه مقادیر باید توی فایل env. یا محیط سیستم تعریف بشن، در غیر این صورت ارور میگیریم. نکته جالب اینه که Pydantic از type cast خودکار پشتیبانی میکنه، مثلا اینجا مقدار "True" توی محیط رو به bool تبدیل میکنه.
و فایل env. باید به این شکل باشه:
DATABASE_URL=postgresql://user:pass@localhost/dbname
SECRET_KEY=s3cr3t-k3y


نحوه ی استفاده از تنظیمات
🛠
میتونیم یه نمونه از کلاس تنظیمات بسازیم و بعد با استفاده از اتریبیوت ها به تنظیمات دسترسی پیدا کنیم:
settings = Settings()
print(settings.database_url)
print(settings.debug)


جمع بندی
✍️
کلاس BaseSettings یکی از ابزارهای بسیار مهم و کاربردی در Pydantic هست که به شما اجازه می‌ده تنظیمات پروژه رو به شکل متمرکز، امن، قابل تست و قابل توسعه مدیریت کنین.
توی پروژه‌های بزرگ یا اپلیکیشن‌هایی که چند محیط (مثل dev، test و prod) دارن، استفاده از این ساختار کمک می‌کنه کد تمیزتر و حرفه‌ای‌تری داشته باشین.

#️⃣ #programming #python


🥷🏻 CHANNEL | GROUP
👍64🔥4