Syntax | سینتکس
2.98K subscribers
423 photos
111 videos
35 files
392 links
Download Telegram
نکات مهم اجرای جنگو با Gunicorn

توضیح درباره Gunicorn
نمیخوام توضیحات زیادی بدم حوصلتون سر بره پس همون سه خط معرفی که تو وب سایت gunicorn نوشته رو براتون یکم شفافش میکنم:
اسمش مخفف green unicorn هستش
جی یونیکورن یک http سرور هستش که از استاندارد WSGI(Web server gateway interface) برای اجرای برنامه های وب پایتون استفاده میکنه.
استاندارد WSGI برای این بوجود اومد تا هر فریم ورک وب پایتونی روش خودشو واسه ارتباط پیاده نکنه و همه از یه استاندارد مشخص استفاده کنن.

در ادامه میگه gunicorn برای unix هستش و برای سیستم عامل هایی مثل مک و لینوکس طراحی شده.

بعدش میگه که جی یونیکورن از مدل pre-fork worker استفاده میکنه حالا این به چه معنیه؟
جی یونیکورن کاری که میکنه اینه قبل اینکه شروع به پردازش درخواست ها کنه، میاد و به اندازه ای که تنظیم کردید worker ایجاد میکنه که هر worker درخواست هارو بطور مستقل پردازش میکنه.

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

قسمت آخرشم میگه light resource هستش و منابع کمی مصرف میکنه همچنین برای ترافیک بالا عملکرد خوبی داره.

خب جی یونیکورن این ادعا هارو میکنه اما بیاید با چند تا مثال شرایطی رو بررسی کنیم که شما به غلط دارید از جی یونیکورن استفاده میکنید:

مثال اول
gunicorn --chdir config config.wsgi:application -b 0.0.0.0:8000

اگه با این دستور جی یونیکورن رو اجرا کنید باید به این نکته دقت کنید بصورت پیشفرض براتون فقط یدونه worker میسازه که این اصلا خوب نیست. خود جی یونیکورن پیشنهاد میده حتی اگه یدونه core دارید 4 تا ورکر بسازید و یه فرمولی هم داده که میگه«تعداد هسته های سی پی یو رو ضربدر 2 به علاوه یک کنید»
همچنین به شما اطمینان داده همین تعداد ورکر هزاران ریکوئست رو میتونن پاسخ بدن پس تعداد ورکر هارو الکی زیادش نکنید.
البته به کیس شما هم بستگی داره.
دستور بهتر برای اجرا اینه تعداد ورکر هارو مشخص کنیم:
gunicorn --workers 5 --chdir config config.wsgi:application -b 0.0.0.0:8000


مثال دوم:
فرض کنید کاربر ها تو اپلیکیشن شما فایل هایی رو آپلود میکنن. شما پنج تا ورکر دارید.
وقتی پنج تا کاربر همزمان فایل آپلود کنن بنظرتون چه اتفاقی میوفته؟
پنج تا ورکر شما گیر یه io افتادن و مشغولن و درخواست های دیگه کاربرا انجام نمیشه. خب این وضعیتی نیست که باب میلیتون باشه!
برای حل این مشکل کافیه از gevent توی جی یونیکرون استفاده گنید؛
gunicorn --workers 1 -k gevent --chdir config config.wsgi:application -b 0.0.0.0:8000

با فلگ -k نوع کلاس ورکر رو مشخص میکنیم. حالا چرا از gevent استفاده میکنیم؟
کتابخونه gevent برای مدریریت همزمانی طراحی شده. میشه گفت یک نمونه lightweight thread هستش که این مدل موقع عملیات های IO سوئیچینگ انجام میده و در این صورت اگه به io خوردید براتون هندل میکنه.

کلی نکات دیگه هم قطعا هست که تو یه پست جا نمیشه
امیدوارم براتون مفید باشه

#python #django #gunicorn #gevent

@Syntax_fa
👍154🔥1🙏1
Linter & pylint

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

کاربردهای Linter


1. شناسایی خطاهای سینتکسی:
لینتر می‌توانند خطاهای سینتکسی را قبل از اجرای کد شناسایی کنند.

2. بهبود خوانایی کد:
با پیشنهادهایی برای رعایت استانداردهای کدنویسی می دهد، خوانایی کد را افزایش می‌دهند.

3. کاهش باگ‌ها:
با شناسایی مسائل بالقوه، به کاهش تعداد باگ‌ها کمک می‌کنند.

4. یکنواختی کد:
با اطمینان از رعایت استانداردهای یکسان در سراسر پروژه، یکنواختی کد را حفظ می‌کنند.

معرفی Pylint

پای لینت یک ابزار Linter برای زبان Python است که به تحلیل کد Python می‌پردازد تا مشکلات مختلفی مانند خطاهای سینتکسی عدم رعایت استانداردهای PEP 8 و مسائل منطقی را شناسایی کند.

ویژگی‌های Pylint


- شناسایی خطاهای نحوی و منطقی:
Pylint می‌تواند خطاهای نحوی و منطقی را در کد شناسایی کند.

- پیشنهاد برای بهبود کد:
با ارائه پیشنهادهایی برای بهبود کد، توسعه‌دهندگان را در نوشتن کدهای تمیزتر و بهینه‌تر یاری می‌دهد.

- پشتیبانی از استانداردهای PEP 8:
با بررسی کد نسبت به استانداردهای PEP 8، به رعایت بهترین شیوه‌های کدنویسی کمک می‌کند.

- گزارش‌دهی جامع:
گزارش‌های کاملی از مشکلات موجود در کد ارائه می‌دهد که شامل امتیازدهی به کیفیت کد نیز می‌باشد.

مثال نحوه استفاده از pylint:
pip install pylint

بعد از نصب کردن با دستور
pylint .

تمامی کد های پروژه را بررسی می کند.
خیلی مواقع نیاز است که لینتر ها و تنظیماتشان را تغییر بدهیم. برای اینکار دستور زیر را میزنیم تا فایل کانفیگ لینتر ساخته شود:
pylint --generate-rcfile > .pylintrc

در فایل .pylintrc می توانید بر حسب نیاز خودتان برخی از لینتر هارا غیر فعال کنید یا تنظیماتشان را تغییر دهید.

نحوه استفاده کاربردی از لینتر:
میتوانید در github workflow از لینتر استفاده کنید و اگر مشکلی شناسایی شد اکشن با خطا مواجه شود. همچنین می توانید از ابزار pre commit استفاده کنید و لینتر را تعریف کنید تا هر زمانی که کامیت جدیدی زده میشود بررسی کند اگر خطایی وجود دارد جلوی کامیت را بگیرد.

#linter #pylint #python

@Syntax_fa
1🔥6👍4
توی پایتون بجای isinstance از singledispatch استفاده کن!

۱. ابتدا دو کلاس با استفاده از @dataclass تعریف میکنیم:
@dataclass
class UserCanceledSubscription:
username: str

@dataclass
class UserSubscribed:
username: str

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

۲. روش اول با استفاده از isinstance:
def process(event):
if isinstance(event, UserSubscribed):
print(f"Enable access to user {event.username}")
elif isinstance(event, UserCanceledSubscription):
print(f"Disable access to user {event.username}")

در این روش، برای هر نوع رویداد یک شرط if نوشته شده که نوع رویداد را چک می‌کند.

۳. روش دوم با استفاده از singledispatch:
@singledispatch
def process(event):
pass

@process.register(UserCanceledSubscription)
def _(event):
print(f"Disable access to user {event.username}")

@process.register(UserSubscribed)
def _(event):
print(f"Enable access to user {event.username}")

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

مزایای استفاده از singledispatch:

۱. کد تمیزتر: به جای زنجیره‌ای از `if/elif`، هر منطق در یک تابع جداگانه قرار می‌گیرد.

۲. قابلیت توسعه بهتر: اضافه کردن نوع جدید فقط نیاز به اضافه کردن یک تابع جدید دارد، نه تغییر کد موجود.

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

۴. کاهش پیچیدگی: به جای یک تابع بزرگ با شرط‌های متعدد، چندین تابع کوچک و ساده داریم.

نحوه کار:
- @singledispatch
یک تابع پایه تعریف می‌کند
- @process.register()
توابع مختلف را برای انواع مختلف ورودی ثبت می‌کند
- در زمان اجرا، بر اساس نوع ورودی، تابع مناسب فراخوانی می‌شود

کاربرد این الگو در مواردی مثل:
- پردازش انواع مختلف پیام‌ها یا رویدادها
- تبدیل داده‌ها بین فرمت‌های مختلف
- اعمال عملیات‌های متفاوت روی انواع مختلف داده
- پیاده‌سازی الگوی Observer یا Event Handler

نمونه استفاده نهایی:
events = [
UserSubscribed(username="johndoe"),
UserCanceledSubscription(username="johndoe"),
]

for event in events:
process(event)


این کد به طور خودکار تابع مناسب را برای هر نوع رویداد فراخوانی می‌کند.

#python #singledispatch

@Syntax_fa
👍17❤‍🔥2🔥1😁1
فایل آپلود شده رو فقط با پسوندش چک می‌کنی؟ بیخیال!

تاحالا شده کاربر فایلی رو آپلود کنه و شما فقط پسوندش ( jpg یا pdf) رو چک کنید و با خوشحالی بگید کار تمومه؟ اگه اینطوره، باید بگم که یه جای کار حسابی می‌لنگه!

کاربر به راحتی می‌تونه یک فایل مخرب (مثلاً یه اسکریپت) رو به virus.png تغییر نام بده و سیستم شما رو دور بزنه.

راه حل چیه؟ کتابخونه python-magic

این پکیج یک رابط (Wrapper) برای کتابخونه قدرتمند libmagic در زبان C هست. کار اصلیش اینه که بیخیال اسم و پسوند فایل بشه و بره سراغ اصل مطلب محتوای خود فایل.

مجیک چند بایت اول یک فایل (که بهش هدر یا Magic Numbers می‌گن) رو می‌خونه و از روی اون امضای دیجیتالی، نوع واقعی فایل رو تشخیص می‌ده.

مثال:
import magic
from django.core.files.uploadedfile import InMemoryUploadedFile

def get_mime_type_from_content(file: InMemoryUploadedFile) -> str:
"""Reads the initial bytes of a file to determine its actual MIME type."""
try:
initial_bytes = file.read(2048)
file.seek(0)
return magic.from_buffer(initial_bytes, mime=True)
except Exception as err:
raise Exception(f"Failed to detect MIME type: {err}")

def check_file_is_image(file: InMemoryUploadedFile) -> bool:
"""Check if the uploaded file is an image based on its MIME type."""
try:
mime_type = get_mime_type_from_content(file)
return mime_type.startswith("image/")
except Exception as err:
print(f"[ERROR] check_file_is_image: {err}")
return False


#libmagic #python_magic

@Syntax_fa
13👍6