Forwarded from Python Hints
این باگ ۱ ماه تیم رو درگیر کرده بود :
توسعه و تست همزمان بصورت پارالل توی تیمهایی که هستم پیش میره (اگر تعداد نیرو کافی باشی)
یک بخشی از کد رو داریم که همهی تست هارو به درستی پشت سر میذاره، حتی تستهایی که توی pipeline و CI/CD داریم
همه چیز حتی بصورت هفتگی روی سیستم ها درست کار میکنه
اما بمحض اینکه میره روی سرور تست خصوصی یا
A/B test
سرعتش تا ۲۰ برابر کندتر میشه شایدم بیشتر
ولی این مشکل رو روی سیستم دولوپرها نداریم.
پیدا کردن این مدل باگها خیلی سخت میتونه باشه، ولی خب بالاخره پیداش کردیم.
مشکل چی بود:
همین خط کد، ۲ تا مسئله داشتیم،
۱- نیروی junior ایی از طرف شرکت به تیم اضافه شده
۲- توی تیم DevOps هم چون کار روتین شده بوده، سپردهاند به یک نیروی Mid-level نگهداری رو
و همزمان ۲ تا خطا انجام شده :
۱- نیروی تیم توسعه و استفاده از
۲- نیروی تیم DevOps و تبدیل یکی از pipeline های تست، ازش پرسیدند چرا انقدر تست طول میکشه بنده خدا رفته چک کرده دیده یک دیتاست بزرگ داریم برای تست
اومده این رو با یک دیتای کوچیکتر جایگزین کرده
و چون نیروی junior توسعه دهنده هم سواد کافی نداشته روی
mylist
توی مثال بالا برای چک کردن اینکه آیا یک نمونهای وجود داره یا نه از
in
استفاده کرده، که روی حجم بالای دیتا منبع اصلی کند بودن هست :
راهکار :
۱- چون روی دیتاهای حجیم کار میکنیم، DevOps نباید دیتای تست رو تغییر میداد (اینجوری باگ خیلی زودتر خودش رو نشون میداد)
۲- نیروی تیم توسعه نباید از in و list استفاده میکرد :
۲-۱ : اول به این دلیل که ما اندیس داده رو نمیخواهیم فقط وجود یا عدم وجودش توی کدها مهم بوده که نوع دادهای set بسیار اینجا کمک کننده بود, همین که بدونیم ۱ مورد وجود داره برامون کفایت میکنه این یعنی فضای جستجو کوچکتر
۲-۲ : دستور in بطور کلی کند هست (برای list, set کوچیک خوبه) باید بجاش از الگوریتمها و ساختمان داده درستش استفاده میکرد که Tree گزینه خوبی هست قطعاً.
دو تا اشتباه همزمان میتونه ۱ ماه همهی تیم رو سردرگم کنه
نکتهی مهم :
حواستون باشه کجا از
توسعه و تست همزمان بصورت پارالل توی تیمهایی که هستم پیش میره (اگر تعداد نیرو کافی باشی)
یک بخشی از کد رو داریم که همهی تست هارو به درستی پشت سر میذاره، حتی تستهایی که توی pipeline و CI/CD داریم
همه چیز حتی بصورت هفتگی روی سیستم ها درست کار میکنه
اما بمحض اینکه میره روی سرور تست خصوصی یا
A/B test
سرعتش تا ۲۰ برابر کندتر میشه شایدم بیشتر
ولی این مشکل رو روی سیستم دولوپرها نداریم.
پیدا کردن این مدل باگها خیلی سخت میتونه باشه، ولی خب بالاخره پیداش کردیم.
مشکل چی بود:
if item in mylist:
همین خط کد، ۲ تا مسئله داشتیم،
۱- نیروی junior ایی از طرف شرکت به تیم اضافه شده
۲- توی تیم DevOps هم چون کار روتین شده بوده، سپردهاند به یک نیروی Mid-level نگهداری رو
و همزمان ۲ تا خطا انجام شده :
۱- نیروی تیم توسعه و استفاده از
in
توی پایتون۲- نیروی تیم DevOps و تبدیل یکی از pipeline های تست، ازش پرسیدند چرا انقدر تست طول میکشه بنده خدا رفته چک کرده دیده یک دیتاست بزرگ داریم برای تست
اومده این رو با یک دیتای کوچیکتر جایگزین کرده
و چون نیروی junior توسعه دهنده هم سواد کافی نداشته روی
mylist
توی مثال بالا برای چک کردن اینکه آیا یک نمونهای وجود داره یا نه از
in
استفاده کرده، که روی حجم بالای دیتا منبع اصلی کند بودن هست :
راهکار :
۱- چون روی دیتاهای حجیم کار میکنیم، DevOps نباید دیتای تست رو تغییر میداد (اینجوری باگ خیلی زودتر خودش رو نشون میداد)
۲- نیروی تیم توسعه نباید از in و list استفاده میکرد :
۲-۱ : اول به این دلیل که ما اندیس داده رو نمیخواهیم فقط وجود یا عدم وجودش توی کدها مهم بوده که نوع دادهای set بسیار اینجا کمک کننده بود, همین که بدونیم ۱ مورد وجود داره برامون کفایت میکنه این یعنی فضای جستجو کوچکتر
۲-۲ : دستور in بطور کلی کند هست (برای list, set کوچیک خوبه) باید بجاش از الگوریتمها و ساختمان داده درستش استفاده میکرد که Tree گزینه خوبی هست قطعاً.
دو تا اشتباه همزمان میتونه ۱ ماه همهی تیم رو سردرگم کنه
نکتهی مهم :
حواستون باشه کجا از
in
استفاده میکنید و مهمتر اگر برای داده حجیم کد میزنید حتماً یکبار روی این حجم داده هم تست انجام بدید.🔥11👍5👏1🤮1
Forwarded from a pessimistic researcher (Kc)
آقای Emanuele Viola استاد دانشگاه Northeastern هستند و حوزه کاریشون Computational Complexity هستش. اگه بخوام خیلی خیلی ساده بگم یعنی دنبال این قضیه هستند که کامپیوتر چه مسائلی رو میتونه حل بکنه و چه مسائلی رو نمیتونه حل بکنه. از وجناتشون اگر بخوام بگم علاوه بر مقالات خیلی خوبشون، مدرس خوبی هم هستند، فیلمای دوتا کلاس طراحی الگوریتم و نظریه محاسباتشون روی کانال یوتیوبشون هست. علاوه براین دست به قلمم هستند و یه وبلاگ خیلی جذاب دارند.
حالا همه اینا رو گفتم که برسیم اینجا. ایشون همین چند ساعت پیش، نسخهی Draft کتابشون رو منتشر کردند. عنوان کتابشون هست : Mathematics of the impossible: Computational Complexity
همونطور که از اسمش پیداست، موضوع کتاب دربارهی نظریه پیچیدگیه و یا همون بحثی که بالاتر گفتم. منتهی فرق خیلی اساسی با کتابای دیگه این حوزه داره. یک، حجم جمع و جوری داره و میشه با یک برنامهریزی خوبی خوندش. دو، برخلاف کتابهای این حوزه اصلا ترسناک نیست، یعنی اینطوری نیست که تا کتاب رو باز میکنی این حس بهت دست بده که زبان کتاب یونانیه. سه، بشدت متن روون و داستان وار و جذابی داره. مثلا توی فصل اولش میاد میگه میخوام یه تیزری از این کتاب بدم، بعد میاد میگه فرض کن یک کامپیوتر داری با ۳ بیت حافظه. این کامپیوتر یه کلاک داره که سر هر پالسش یکی از این دو عملیات رو انجام میده، یا یک بیت دیتا ورودی میخونه و حافظه رو آپدت میکنه، و یا متوقف میشه و یک مقداری رو برمیگردونه.
با همین کامپیوتر ساده شروع میکنه مسئله حل کردن. مسئلهی AND یک رشته n بیتی، مسئلهی چک کردن پالیندورم بودن یک رشته n بیتی و میرسه به مسئلهی Majority یک رشته n بیتی، یعنی بیش از نصف رشته اگر یک بود، روی یک توافق میشه و اگر نصف بیشتر رشته صفر بود روی صفر توافق میشه. سوالی مطرح میکنند که هر کسی در مرحلهی اول جوابش رو میگه نه، ولی متوجه میشید که میشه مسئله رو در زمانی که مد نظر مسئله هست حل کرد! و همونجا متوجه میشید که چقدر ارزش این علم بالاست.
خلاصه همینطوری فصل به فصل میان جلو و توی فصل آخر میگن I believe P=NP :))))
سر این قضیه که P = NP باشه خوبه یا بده قبلا یه پست توی کانال رفتم که بدون داشتن ذرهای سواد نظریه پیچیدگی میتونید متوجهاش بشید. پسته اینجاست.
حالا همه اینا رو گفتم که برسیم اینجا. ایشون همین چند ساعت پیش، نسخهی Draft کتابشون رو منتشر کردند. عنوان کتابشون هست : Mathematics of the impossible: Computational Complexity
همونطور که از اسمش پیداست، موضوع کتاب دربارهی نظریه پیچیدگیه و یا همون بحثی که بالاتر گفتم. منتهی فرق خیلی اساسی با کتابای دیگه این حوزه داره. یک، حجم جمع و جوری داره و میشه با یک برنامهریزی خوبی خوندش. دو، برخلاف کتابهای این حوزه اصلا ترسناک نیست، یعنی اینطوری نیست که تا کتاب رو باز میکنی این حس بهت دست بده که زبان کتاب یونانیه. سه، بشدت متن روون و داستان وار و جذابی داره. مثلا توی فصل اولش میاد میگه میخوام یه تیزری از این کتاب بدم، بعد میاد میگه فرض کن یک کامپیوتر داری با ۳ بیت حافظه. این کامپیوتر یه کلاک داره که سر هر پالسش یکی از این دو عملیات رو انجام میده، یا یک بیت دیتا ورودی میخونه و حافظه رو آپدت میکنه، و یا متوقف میشه و یک مقداری رو برمیگردونه.
با همین کامپیوتر ساده شروع میکنه مسئله حل کردن. مسئلهی AND یک رشته n بیتی، مسئلهی چک کردن پالیندورم بودن یک رشته n بیتی و میرسه به مسئلهی Majority یک رشته n بیتی، یعنی بیش از نصف رشته اگر یک بود، روی یک توافق میشه و اگر نصف بیشتر رشته صفر بود روی صفر توافق میشه. سوالی مطرح میکنند که هر کسی در مرحلهی اول جوابش رو میگه نه، ولی متوجه میشید که میشه مسئله رو در زمانی که مد نظر مسئله هست حل کرد! و همونجا متوجه میشید که چقدر ارزش این علم بالاست.
خلاصه همینطوری فصل به فصل میان جلو و توی فصل آخر میگن I believe P=NP :))))
سر این قضیه که P = NP باشه خوبه یا بده قبلا یه پست توی کانال رفتم که بدون داشتن ذرهای سواد نظریه پیچیدگی میتونید متوجهاش بشید. پسته اینجاست.
🔥7👍1🤮1
Forwarded from لوپینو | آموزش برنامه نویسی Loopino
🔵 آشنایی با defaultdict در پایتون
در هنگام استفاده از دیکشنریهای پایتونی، گاهی به کلیدهایی برمیخوریم که از قبل در دیکشنری ما وجود ندارند و این اتفاق، باعث دریافت خطا در برنامه میشود. کانتینر defaultdict قرار است در حل این مسئله به ما کمک کند؛ با مطالعه این پست با این امکان از زبان پایتون آشنا میشوید.
#پایتون #Python
لوپینو | آموزش های برنامه نویسی
• Telegran: @loopino
• Instagram: https://www.instagram.com/loopino_fa/
در هنگام استفاده از دیکشنریهای پایتونی، گاهی به کلیدهایی برمیخوریم که از قبل در دیکشنری ما وجود ندارند و این اتفاق، باعث دریافت خطا در برنامه میشود. کانتینر defaultdict قرار است در حل این مسئله به ما کمک کند؛ با مطالعه این پست با این امکان از زبان پایتون آشنا میشوید.
#پایتون #Python
لوپینو | آموزش های برنامه نویسی
• Telegran: @loopino
• Instagram: https://www.instagram.com/loopino_fa/
👍5🤮1
Forwarded from Python BackendHub
یکی دیگه از کاربرد های fingerprinting میتونه request limit باشه.
تو هر api شما نیاز دارین برای gateway سرویس هاتون یک لیمیت بنویسید که کسی شما رو ddos نکنه.
یکی از راه حل های ابتدایی استفاده از IP Address هست. البته بخاطر وجود CGNAT عملا راهکار جالبی نیست چون هکر میتونه پشت CGNAT قایم شه که شما وایت لیست کردین و همچنان سیستمتون رو پایین بیاره.
پس برای یک راهکار safe باید چیکار کرد؟
1. برای روتر های private: از authentication header استفاده کنید و ریت لیمیت رو روی اون بذارین. در حالی که میتونه راه حل بنظر مناسبی باشه ولی هکر میتونه تعداد زیادی کاربر بسازه و با JWT هر کدوم بازم اسپم کنه. پس بازم راهکار کاملی نیست.
2. برای روتر ثبت نام: لیمیت کردن و حساسیت رو سرویس ثبت نام به ازای هر آی پی بدون داشتن وایت لیستی برای CGNATکه به طور periodic بلک لیست کنه اون آی پی رو و بعد چند ساعت دوباره بتونه حساب کاربری بسازه.
3. برای روتر پابلیک : استفاده از browser fingerprinting برای تشخیص دیوایس کاربر و گذاشتن ریمیت لیت روی ترکیب GPU fingerprint (مثل webgl یا webtrc) و IP بدون هیچ وایت لیستی. همین تکنیک میتونه رو روتر ثبت نام هم پیاده شه تا حساسیت روتر ثبت نام رو روی CGNAT کم کنه.
راهکار سوم راهکاریه که ddos shield ها ازش استفاده میکنن مثل cloudflare. راهکار بهترش اینه که خودتون مدل کاستومایز و فینگرپرینت مخصوص خودتون داشته باشین یا از سرویس پرمیومشون استفاده کنید که فایل جاوا اسکریپتشو تند تند آپدیت میکنن و به اطلاعات ویزیتور ها هم دسترسی میدن.
از نمونه سایت هایی که از راهکار سوم استفاده میکنن:
Sony Entertainment
Apple Store
Youtube
برای دیدن browser fıngerprint خودتون به این صفحه برین
@ManiFoldsPython
تو هر api شما نیاز دارین برای gateway سرویس هاتون یک لیمیت بنویسید که کسی شما رو ddos نکنه.
یکی از راه حل های ابتدایی استفاده از IP Address هست. البته بخاطر وجود CGNAT عملا راهکار جالبی نیست چون هکر میتونه پشت CGNAT قایم شه که شما وایت لیست کردین و همچنان سیستمتون رو پایین بیاره.
پس برای یک راهکار safe باید چیکار کرد؟
1. برای روتر های private: از authentication header استفاده کنید و ریت لیمیت رو روی اون بذارین. در حالی که میتونه راه حل بنظر مناسبی باشه ولی هکر میتونه تعداد زیادی کاربر بسازه و با JWT هر کدوم بازم اسپم کنه. پس بازم راهکار کاملی نیست.
2. برای روتر ثبت نام: لیمیت کردن و حساسیت رو سرویس ثبت نام به ازای هر آی پی بدون داشتن وایت لیستی برای CGNATکه به طور periodic بلک لیست کنه اون آی پی رو و بعد چند ساعت دوباره بتونه حساب کاربری بسازه.
3. برای روتر پابلیک : استفاده از browser fingerprinting برای تشخیص دیوایس کاربر و گذاشتن ریمیت لیت روی ترکیب GPU fingerprint (مثل webgl یا webtrc) و IP بدون هیچ وایت لیستی. همین تکنیک میتونه رو روتر ثبت نام هم پیاده شه تا حساسیت روتر ثبت نام رو روی CGNAT کم کنه.
راهکار سوم راهکاریه که ddos shield ها ازش استفاده میکنن مثل cloudflare. راهکار بهترش اینه که خودتون مدل کاستومایز و فینگرپرینت مخصوص خودتون داشته باشین یا از سرویس پرمیومشون استفاده کنید که فایل جاوا اسکریپتشو تند تند آپدیت میکنن و به اطلاعات ویزیتور ها هم دسترسی میدن.
از نمونه سایت هایی که از راهکار سوم استفاده میکنن:
Sony Entertainment
Apple Store
Youtube
برای دیدن browser fıngerprint خودتون به این صفحه برین
@ManiFoldsPython
👍1🤮1
Forwarded from Python BackendHub
تجربه شخصی خودم از روند مصاحبه و نصیحت هایی که به مانی 3 ماه پیش میکردم 😁
1. OVERENGINEER AS MUCH AS YOU CAN
اولین و مهم ترین چیز همینه. این تجربم برمیگرده به مصاحبه اولم. لایو کدینگی که یک ساعت بود ولی 2 ساعت و نیم طول کشید 😂😂. آخر لایو کدینگ هم که 95درصد کدو نوشته بودم منو متوقف کرد و گفت کافیه. به من یک کدی نشون داد که همون کاری که من میخواستم بکنم رو تو 15 خط کد پایتون میکرد. من گفتم ریجکت شدم تموم شد رفت. پس فرداش آفر کاریش اومد و الان تو همون شرکت کار میکنم. گفت اگه رو پروداکشن اینطوری overengineer کنی دارت میزنم :)). شما با overengineer کردن تو لایو کد چلنج یا assigement مهارتتون رو show off میکنید و طبیعتا اجازه میده بهتون که نسبت به بقیه کاندید ها که تلاش داشتن KIS رو رعایت کنند جلو بیفتین و اون طرف متوجه شه که شما از کجا میاین (ترجمه I see where you're coming from😁) ریپوش اینجاست. اینکه چرا انتخاب شدم هم خوش یک سکشن جداست.
2. Try new technologies, don't be afraid of rejection
اینکه قبلا جنگو کار کردین ولی برای fast اقدام نمیکنید اشتباهه بنظرم. اگه اشتیاق کار کردن با اون استکو دارین حتما اپلای کنید. ملاک استخدام فقط بلد بودن و تسلط رو اون تکنولوژی نیست خیلی وقتا شانس اینو دارین رو تکنولوژی آفر بگیرین که شاید خیلی روش مسلط نیستین و صرفا آشنا هستین در صورتی که تو job requirement نوشته مسلط. مثال بارزش دوباره از خودم میزنم. من همیشه rest کار کردم. کل بک شرکتی که داشتم براش اپلای میکردم graphql بود و خیلی تاکید داشت روی تجربه با graphql. تو مصاحبه اول اصلا اشاره نکردم به اینکه هیچی از graphql بارم نیست. تو مرحله assignment یک هفته داکشو خوندم. شاید باورتون نشه ولی جاب آفر از اون پوزیشنم گرفتم :)) . پس دلیل نمیشه شما یک چیزی رو بلد نیستین تو آگهی بهش اشاره شده اپلای نکنید. تهش اینه که با اون تکنولوژی آشنا میشین.
3. THINK, THEN CODE
این از همه مهم تره. مهم ترین چیز critical thinking هست براشون. اینکه شما صرفا هدفتون انجام اون تسک نباشه. هدفتون هدف اون تسک باشه. حتی نیازی نیست از راهی که اشاره شده تو داکیومنت assignment برین. مثلا برای همین graphql پجینشن میخواست که من از راه حلی که خودش معرفی کرده بود نرفتم چون بنظره من اورلود نتورک داشت. راه حلشو تغییر دادم و یکی از دلایل اصلی قبول شدنم همین بود. یا اینکه مثلا درخواست رو نگفته بود async بزن ولی من درخواست اول رو sync میزدم که ببینم چند تا آیتم داریم بگیریم بعد به تعداد درخواست ها همرو تو سری دوم باهم async میزدم (که network efficient هم باشه و الکی اسپم نکنه). سورس کد ریپو. همه اینا نشون داد که به صورت مسئله حسابی فکر کردم. تو پوینت اولم فقط OVER-ENGINEER نکردم به صورت مسئله هم حسابی فکر کردم. سعی کردم تا جایی که میشه efficient باشه حتی شده با نقض داکیومنت assignment. هیچ شرکتی دنبال کسی نیست که فقط کپی پیست کنه یا فقط کاری که بهش میگن رو انجام بده و تک بعدی باشه, کد نویس ایده آل کسیه که خیلی فکر میکنه و میتونه راهکار نو و بهتر از راهکار قدیمی بده. با وجود اینکه من سابقه کار fastapi به صورت حرفه ای نداشتم یا graphql بلد نبودم چون صرفا thinker بودنمو خوب نشون دادم تونستم به این موفقیت برسم. از نمونه ریجکتیم هم بخوام بگم باید بگم یک assignment ام ریجکت شد و حتی فیدبک هم نگرفت چون خوب روش فکر نکرده بودم و صرفا کاری که بهم گفته بودن رو به ساده ترین شکل ممکن پیاده سازی کردم (انگار که رفع تکلیف باشه).
The most damaging phrease in the language is 'its always been done this way' - Grace Hopper
@ManiFoldsPython
1. OVERENGINEER AS MUCH AS YOU CAN
اولین و مهم ترین چیز همینه. این تجربم برمیگرده به مصاحبه اولم. لایو کدینگی که یک ساعت بود ولی 2 ساعت و نیم طول کشید 😂😂. آخر لایو کدینگ هم که 95درصد کدو نوشته بودم منو متوقف کرد و گفت کافیه. به من یک کدی نشون داد که همون کاری که من میخواستم بکنم رو تو 15 خط کد پایتون میکرد. من گفتم ریجکت شدم تموم شد رفت. پس فرداش آفر کاریش اومد و الان تو همون شرکت کار میکنم. گفت اگه رو پروداکشن اینطوری overengineer کنی دارت میزنم :)). شما با overengineer کردن تو لایو کد چلنج یا assigement مهارتتون رو show off میکنید و طبیعتا اجازه میده بهتون که نسبت به بقیه کاندید ها که تلاش داشتن KIS رو رعایت کنند جلو بیفتین و اون طرف متوجه شه که شما از کجا میاین (ترجمه I see where you're coming from😁) ریپوش اینجاست. اینکه چرا انتخاب شدم هم خوش یک سکشن جداست.
2. Try new technologies, don't be afraid of rejection
اینکه قبلا جنگو کار کردین ولی برای fast اقدام نمیکنید اشتباهه بنظرم. اگه اشتیاق کار کردن با اون استکو دارین حتما اپلای کنید. ملاک استخدام فقط بلد بودن و تسلط رو اون تکنولوژی نیست خیلی وقتا شانس اینو دارین رو تکنولوژی آفر بگیرین که شاید خیلی روش مسلط نیستین و صرفا آشنا هستین در صورتی که تو job requirement نوشته مسلط. مثال بارزش دوباره از خودم میزنم. من همیشه rest کار کردم. کل بک شرکتی که داشتم براش اپلای میکردم graphql بود و خیلی تاکید داشت روی تجربه با graphql. تو مصاحبه اول اصلا اشاره نکردم به اینکه هیچی از graphql بارم نیست. تو مرحله assignment یک هفته داکشو خوندم. شاید باورتون نشه ولی جاب آفر از اون پوزیشنم گرفتم :)) . پس دلیل نمیشه شما یک چیزی رو بلد نیستین تو آگهی بهش اشاره شده اپلای نکنید. تهش اینه که با اون تکنولوژی آشنا میشین.
3. THINK, THEN CODE
این از همه مهم تره. مهم ترین چیز critical thinking هست براشون. اینکه شما صرفا هدفتون انجام اون تسک نباشه. هدفتون هدف اون تسک باشه. حتی نیازی نیست از راهی که اشاره شده تو داکیومنت assignment برین. مثلا برای همین graphql پجینشن میخواست که من از راه حلی که خودش معرفی کرده بود نرفتم چون بنظره من اورلود نتورک داشت. راه حلشو تغییر دادم و یکی از دلایل اصلی قبول شدنم همین بود. یا اینکه مثلا درخواست رو نگفته بود async بزن ولی من درخواست اول رو sync میزدم که ببینم چند تا آیتم داریم بگیریم بعد به تعداد درخواست ها همرو تو سری دوم باهم async میزدم (که network efficient هم باشه و الکی اسپم نکنه). سورس کد ریپو. همه اینا نشون داد که به صورت مسئله حسابی فکر کردم. تو پوینت اولم فقط OVER-ENGINEER نکردم به صورت مسئله هم حسابی فکر کردم. سعی کردم تا جایی که میشه efficient باشه حتی شده با نقض داکیومنت assignment. هیچ شرکتی دنبال کسی نیست که فقط کپی پیست کنه یا فقط کاری که بهش میگن رو انجام بده و تک بعدی باشه, کد نویس ایده آل کسیه که خیلی فکر میکنه و میتونه راهکار نو و بهتر از راهکار قدیمی بده. با وجود اینکه من سابقه کار fastapi به صورت حرفه ای نداشتم یا graphql بلد نبودم چون صرفا thinker بودنمو خوب نشون دادم تونستم به این موفقیت برسم. از نمونه ریجکتیم هم بخوام بگم باید بگم یک assignment ام ریجکت شد و حتی فیدبک هم نگرفت چون خوب روش فکر نکرده بودم و صرفا کاری که بهم گفته بودن رو به ساده ترین شکل ممکن پیاده سازی کردم (انگار که رفع تکلیف باشه).
The most damaging phrease in the language is 'its always been done this way' - Grace Hopper
@ManiFoldsPython
GitHub
GitHub - ManiMozaffar/pokemon-api-challenge: Short API challenge, implemented using MVC SOLID design
Short API challenge, implemented using MVC SOLID design - ManiMozaffar/pokemon-api-challenge
👍2🤮1
Forwarded from Ali Mesforush
@LATEX_Mesforush
در کانال آکادمی دکتر مسفروش میتوانید تعداد زیادی از دروس ریاضی و کامپیوتر مرتبط با رشتههای فنی و مهندسی و علوم پایه را که منطبق با سرفصل وزارت علوم، تحقیقات و فناوری و به طور کامل تدریس شدهاند را بیابید. تمامی این دروس به شکل کامل و صد در صد رایگان بوده و با هدف برقراری عدالت آموزشی تهیه شدهاند.
@LATEX_Mesforush
در کانال آکادمی دکتر مسفروش میتوانید تعداد زیادی از دروس ریاضی و کامپیوتر مرتبط با رشتههای فنی و مهندسی و علوم پایه را که منطبق با سرفصل وزارت علوم، تحقیقات و فناوری و به طور کامل تدریس شدهاند را بیابید. تمامی این دروس به شکل کامل و صد در صد رایگان بوده و با هدف برقراری عدالت آموزشی تهیه شدهاند.
@LATEX_Mesforush
❤3🤮1
Forwarded from برنامه نویسی از پایه
Media is too big
VIEW IN TELEGRAM
برنامه نویسی از پایه قسمت شصتم - اضافه کردن داشبورد
این قسمت رو با اضافه کردن اپ جدید شروع کردیم و اتفاقی با ماژول پروفایل و مفهوم profiler در پایتون آشنا شدیم. بعدش با مشکل cache مواجه شدیم و حلش کردیم. در ادامه متوجه شدیم که وقتی از یک تمپلت ارث بری می کنیم، جنگو اولویت استفاده از تمپلت base رو براساس app هایی که توی installed_app هستن تنظیم میکنه. و اگه دو تا base همنام داشته باشیم اولویت با اونی هست که بالاتر به installed_app اضافه شده. بعدش با flex-grow و justify-content و align-items توی css آشنا شدیم. در ادامه با مفهوم Semantic elemnts توی HTML5 هم بیشتر آشنا شدیم و بهترین روش برای نوشتن کدهامون رو از اینترنت سرچ کردیم. در نهایت بعد از ۳۰ دقیقه تونستیم یه تگ h1 به پروژه اضافه کنیم. عجب سرعت عملی
لینک آپارات:
https://www.aparat.com/v/qkZw3
لینک یوتیوب:
https://youtu.be/bvGGQ-7HKiY
این قسمت رو با اضافه کردن اپ جدید شروع کردیم و اتفاقی با ماژول پروفایل و مفهوم profiler در پایتون آشنا شدیم. بعدش با مشکل cache مواجه شدیم و حلش کردیم. در ادامه متوجه شدیم که وقتی از یک تمپلت ارث بری می کنیم، جنگو اولویت استفاده از تمپلت base رو براساس app هایی که توی installed_app هستن تنظیم میکنه. و اگه دو تا base همنام داشته باشیم اولویت با اونی هست که بالاتر به installed_app اضافه شده. بعدش با flex-grow و justify-content و align-items توی css آشنا شدیم. در ادامه با مفهوم Semantic elemnts توی HTML5 هم بیشتر آشنا شدیم و بهترین روش برای نوشتن کدهامون رو از اینترنت سرچ کردیم. در نهایت بعد از ۳۰ دقیقه تونستیم یه تگ h1 به پروژه اضافه کنیم. عجب سرعت عملی
لینک آپارات:
https://www.aparat.com/v/qkZw3
لینک یوتیوب:
https://youtu.be/bvGGQ-7HKiY
👍5❤1🤮1
Forwarded from برنامه نویسی از پایه
Media is too big
VIEW IN TELEGRAM
برنامه نویسی از پایه قسمت شصت و یکم - اصلاح کدها
توی این قسمت که حدودا ۱۰ دقیقه است. یه ایرادی رو برطرف کردیم که توی جلسه قبلی بهش دقت نکرده بودیم. بعدش باز یکم در مورد display direction و مفاهیم felx یاد گرفتیم. در نهایت هیچی به کدهای html اضافه نشد. و همچنان عجب سرعت عملی :)
لینک آپارات:
https://www.aparat.com/v/8q4y5
لینک یوتیوب:
https://youtu.be/YCgdErR2wBA
توی این قسمت که حدودا ۱۰ دقیقه است. یه ایرادی رو برطرف کردیم که توی جلسه قبلی بهش دقت نکرده بودیم. بعدش باز یکم در مورد display direction و مفاهیم felx یاد گرفتیم. در نهایت هیچی به کدهای html اضافه نشد. و همچنان عجب سرعت عملی :)
لینک آپارات:
https://www.aparat.com/v/8q4y5
لینک یوتیوب:
https://youtu.be/YCgdErR2wBA
👍4🤮1
✅ از کانال @microfrontend_ir
در اغلب مصاحبه های فنی جنگو سوال کاربرد select_related پرسیده میشود با این وجو اغلب اهمیت این فانکشن نادیده گرفته می شود. عدم استفاده ویژگی مهم select_related در Django ORM میتواند تاثیر منفی سنگینی در اپلیکیشن داشته باشد. در این ویدیو کوتاه با یک مثال ساده سعی کردم تفاوت استفاده و عدم استفاده از django select_related را توضیح دهم
Video Link: https://youtu.be/TK3P4Cy5fNg
یادآوری ذکر شده در ویدیو:
همه چیز در مورد لاگ زدن در پایتون - Python Logging
https://youtu.be/32l7Wogtsxk
پیکربندی لاگ زدن در جنگو - django logging
https://youtu.be/LGatKmpL7k8
〰️〰️〰️〰️〰️〰️
© | @microfrontend_ir
در اغلب مصاحبه های فنی جنگو سوال کاربرد select_related پرسیده میشود با این وجو اغلب اهمیت این فانکشن نادیده گرفته می شود. عدم استفاده ویژگی مهم select_related در Django ORM میتواند تاثیر منفی سنگینی در اپلیکیشن داشته باشد. در این ویدیو کوتاه با یک مثال ساده سعی کردم تفاوت استفاده و عدم استفاده از django select_related را توضیح دهم
Video Link: https://youtu.be/TK3P4Cy5fNg
یادآوری ذکر شده در ویدیو:
همه چیز در مورد لاگ زدن در پایتون - Python Logging
https://youtu.be/32l7Wogtsxk
پیکربندی لاگ زدن در جنگو - django logging
https://youtu.be/LGatKmpL7k8
〰️〰️〰️〰️〰️〰️
© | @microfrontend_ir
👍4🤮1
Forwarded from ProgrammingSchool (Python)
ارسال آرگومانها با تعداد نامشخص به تابع
زمانیکه تعداد آرگومانهای ارسالی به یک تابع نامشخص باشد کافی است از علامت * در کنار نام پارامتر استفاده شود.
زمانیکه از آرگومانهای ستارهدار استفاده میشود در هنگام فراخوانی تابع نمیتوان آرگومان ستارهدار را به صورت parameter = arguman تعریف کرد. همانطور که در مثال اول مشاهده میشود سه مقدار 3 ، 2 و 5 به عنوان آرگومان به تابع ارسال میشوند. تابع، آنها را در قالب یک تاپل در نظر میگیرد. در انتها این تاپل نمایش داده میشود.
نکته دیگر این است که تمام آرگومانهای بعد از آرگومان ستارهدار باید به صورت parameter = arguman تعریف شوند.😊 همانطور که در مثال دوم مشاهده میشود آرگومان c ، که بعد از آرگومان ستارهدار b قرار دارد در هنگام فراخوانی به صورت c=4 تعریف شده است.
#آموزش_پایتون
#توابع
#آرگومان
آدرس کانال:
@Programmingschool2
سایت آموزشی:
http://programmingschool.ir
گروه پرسش و پاسخ:
https://t.me/programmingschool_group
زمانیکه تعداد آرگومانهای ارسالی به یک تابع نامشخص باشد کافی است از علامت * در کنار نام پارامتر استفاده شود.
زمانیکه از آرگومانهای ستارهدار استفاده میشود در هنگام فراخوانی تابع نمیتوان آرگومان ستارهدار را به صورت parameter = arguman تعریف کرد. همانطور که در مثال اول مشاهده میشود سه مقدار 3 ، 2 و 5 به عنوان آرگومان به تابع ارسال میشوند. تابع، آنها را در قالب یک تاپل در نظر میگیرد. در انتها این تاپل نمایش داده میشود.
نکته دیگر این است که تمام آرگومانهای بعد از آرگومان ستارهدار باید به صورت parameter = arguman تعریف شوند.😊 همانطور که در مثال دوم مشاهده میشود آرگومان c ، که بعد از آرگومان ستارهدار b قرار دارد در هنگام فراخوانی به صورت c=4 تعریف شده است.
#آموزش_پایتون
#توابع
#آرگومان
آدرس کانال:
@Programmingschool2
سایت آموزشی:
http://programmingschool.ir
گروه پرسش و پاسخ:
https://t.me/programmingschool_group
👍4🤮1
✅ پست جالبی از کانال @productdraft
پشم های گاومیش رو نزن
موقعیتی رو در نظر بگیرین که
میخواین ماشین تون رو بشورین
اما شلنگ خرابه
میخواین شلنگ بخرین اما فروشگاه بیرون شهره و عوارضی میخواد
همسایه تون کارت عوارضی داره
میرین کارت رو بگیرین میگه چون قبلاً یه بالشت بهتون قرض داده تا اون بالشت رو نیارین کارت رو نمیده
میرین بالشت رو بیارین میبینین یه خرده خالی شده و لازمه یه خورده پشم و اینا جور کنین که درست بشه
و در نهایت میبینین روزی رو که برای ماشین شستن شروع کردین تموم شده و شما دارین پشم گاومیش رو میزنین
در حالی که سطل برا شستن ماشین داشتین
این اصطلاح مربوط به چیزهایی میشه که ما برای انجام دادن شروع شون میکنیم اما میبینیم یه ناقصی داره و هعی یه مرحله میریم عقب که ناقصی رو درست کنیم
جای اینکه یه گام مشکل رو جلو ببریم و حلش کنیم
یه گام مشکل ما رو عقب میبره و ما رو از حل کردنش وا میداره
مسأله اینجاست که خیلی در توسعه محصول رایجه
میری یه مساله کاربر رو حل کنی میبینی که اااا فلان بخش مرتبط با دیتا، دیتا خوب جمع نمیکنه، میری دیتا رو درست کنی میبینی مشکل معماری و کد داری، میری معماری رو درست کنی میبینی سخت افزار کم داری نهایت خودتو وسط دیتاسنتر میبینی
در حالی که مشکل کاربر نه صددرصد ولی تا هفتاد درصد با همون دیتا قابل حل بود
دلیل رایجش اون جوری که خودم تجربه کردم
گم شدن هدفه
اونم هدفی که تو هر مرحله نچرخونیش
هدف درجه یک هر مسالهای که شروع میشه (بیزینسی یا کاربری) نباید تو مسیر گم بشه چون مشکل واقعی هم با هدفش گم میشه
پشم های گاومیش رو نزن
موقعیتی رو در نظر بگیرین که
میخواین ماشین تون رو بشورین
اما شلنگ خرابه
میخواین شلنگ بخرین اما فروشگاه بیرون شهره و عوارضی میخواد
همسایه تون کارت عوارضی داره
میرین کارت رو بگیرین میگه چون قبلاً یه بالشت بهتون قرض داده تا اون بالشت رو نیارین کارت رو نمیده
میرین بالشت رو بیارین میبینین یه خرده خالی شده و لازمه یه خورده پشم و اینا جور کنین که درست بشه
و در نهایت میبینین روزی رو که برای ماشین شستن شروع کردین تموم شده و شما دارین پشم گاومیش رو میزنین
در حالی که سطل برا شستن ماشین داشتین
این اصطلاح مربوط به چیزهایی میشه که ما برای انجام دادن شروع شون میکنیم اما میبینیم یه ناقصی داره و هعی یه مرحله میریم عقب که ناقصی رو درست کنیم
جای اینکه یه گام مشکل رو جلو ببریم و حلش کنیم
یه گام مشکل ما رو عقب میبره و ما رو از حل کردنش وا میداره
مسأله اینجاست که خیلی در توسعه محصول رایجه
میری یه مساله کاربر رو حل کنی میبینی که اااا فلان بخش مرتبط با دیتا، دیتا خوب جمع نمیکنه، میری دیتا رو درست کنی میبینی مشکل معماری و کد داری، میری معماری رو درست کنی میبینی سخت افزار کم داری نهایت خودتو وسط دیتاسنتر میبینی
در حالی که مشکل کاربر نه صددرصد ولی تا هفتاد درصد با همون دیتا قابل حل بود
دلیل رایجش اون جوری که خودم تجربه کردم
گم شدن هدفه
اونم هدفی که تو هر مرحله نچرخونیش
هدف درجه یک هر مسالهای که شروع میشه (بیزینسی یا کاربری) نباید تو مسیر گم بشه چون مشکل واقعی هم با هدفش گم میشه
👍18👏2🤯2🤮1
جنگولرن
مطلبی درباره تفاوت == و is از کانال @osmanpydev
✅ مطلبی در مورد تفاوت == و is از کانال @osmanpydev
ما وقتی ی متغیر میسازیم، مثلا ی لیست، به این صورت:
list1 = [1, 2, 3, 4]
این متغیری که لیستمون رو بهش نسبت دادیم به ی خونه از حافظه رم اشاره میکنه، یعنی این لیست رو داخل ی خونه رم میذاره و به آدرس اون خونه اشاره میکنه.
حالا ی لیست دیگه بسازیم:
list2 = list1
در واقع ما گفتیم لیست دوم هم به همون آدرسی که لیست یک اشاره میکرد اشاره کنه.
حالا هر تغییری تو لیست یک یا لیست دو ایجاد کنیم اون یکی هم تغییر میکنه، مثلا:
list2.append(5)
نتیجه میشه:
print(list1) -> [1, 2, 3, 4, 5]
print(list2) -> [1, 2, 3, 4, 5]
ولی اگه بیایم بگیم:
list3 = list1[:]
اینجا میگیم ی لیست بساز و آیتمهای لیست یک رو بریز داخلش، ولی نگفتیم لیست سه = لیست یک؛ بنابراین لیست سه به ی خونه دیگه از حافظه رم اشاره میکنه ولی مقدارش همون مقدار لیست یک هست.
به این ترتیب اگه بگیم:
list3.append(6)
نتیجه میشه:
print(list1) -> [1, 2, 3, 4, 5]
print(list2) -> [1, 2, 3, 4, 5]
print(list3) -> [1, 2, 3, 4, 5, 6]
چون ما دیتای ی خونه دیگه از حافظه رم رو تغییر دادیم و فقط مقدار متغیری که به اون خونه اشاره میکنه تغییر کرد.
برای متوجه شدن این تفاوت میتونید با دستور زیر نتیجه رو ببینید:
print(id(list1))
print(id(list2))
print(id(list3))
تابع id آدرس خونهای که متغیر بهش اشاره میکنه رو میده، اینجا لیست یک و لیست دو ی چیز رو چاپ میکنن ولی لیست سه ی چیز دیگه رو چاپ میکنه.
حالا علامت == فقط مقدار دو تا متغیر رو با هم مقایسه میکنه ولی علامت is میاد هم مقدارشون و هم اینکه به ی خونه اشاره میکنن یا نه رو بررسی میکنه، پس:
list1 is list2 -> True
list1 == list2 -> True
list1 is list3 -> False
list1 == list3 -> False (البته چون اونجا ۶ رو به لیست سه اضافه کردیم)
قبل append
list1 == list3 -> True
این همون مفهوم (کپی سطحی)shallow copy در پایتونه.
روش اول کپی نکرد، بلکه آدرس خونه رم رو به متغیر دوم نسبت داد ولی دومی کپی سطحی کرد.
حالا فرض کنید لیست اول رو به این صورت تعریف کردیم:
list1 = [1, 2, [3, 4], 5]
یعنی ی لیست دیگه هم بعنوان ی آیتم بهش دادیم، یعنی بعبارتی لیست تو در تو ایجاد کردیم.
اینجا اگه از روش کپی سطحی استفاده کنیم بازم همون مشکل اول بوجود میاد؛ چون باز آدرس خونه رم لیست داخلی رو داد به متغیر دومی.
list2 = list1[:]
حالا فرض کنید تغییر رو بصورت زیر اعمال کردیم:
list2[2][0] = 9
دوباره خروجی لیست اول رو ببینید:
print(list1) -> [1, 2, [9, 4], 5]
چطور میتونیم جلوی این مشکل رو بگیریم و بعبارتی ی (کپی عمیق)deepcopy داشته باشیم؟
با استفاده از کتابخونه داخلی copy:
import copy
list2 = copy.deepcopy(list1)
البته میشه با همین کتابخونه هم ی کپی سطحی داشت، بصورت زیر:
list3 = copy.copy(list1)
سعی میکنم بیشتر درموردش صحبت کنم.
ما وقتی ی متغیر میسازیم، مثلا ی لیست، به این صورت:
list1 = [1, 2, 3, 4]
این متغیری که لیستمون رو بهش نسبت دادیم به ی خونه از حافظه رم اشاره میکنه، یعنی این لیست رو داخل ی خونه رم میذاره و به آدرس اون خونه اشاره میکنه.
حالا ی لیست دیگه بسازیم:
list2 = list1
در واقع ما گفتیم لیست دوم هم به همون آدرسی که لیست یک اشاره میکرد اشاره کنه.
حالا هر تغییری تو لیست یک یا لیست دو ایجاد کنیم اون یکی هم تغییر میکنه، مثلا:
list2.append(5)
نتیجه میشه:
print(list1) -> [1, 2, 3, 4, 5]
print(list2) -> [1, 2, 3, 4, 5]
ولی اگه بیایم بگیم:
list3 = list1[:]
اینجا میگیم ی لیست بساز و آیتمهای لیست یک رو بریز داخلش، ولی نگفتیم لیست سه = لیست یک؛ بنابراین لیست سه به ی خونه دیگه از حافظه رم اشاره میکنه ولی مقدارش همون مقدار لیست یک هست.
به این ترتیب اگه بگیم:
list3.append(6)
نتیجه میشه:
print(list1) -> [1, 2, 3, 4, 5]
print(list2) -> [1, 2, 3, 4, 5]
print(list3) -> [1, 2, 3, 4, 5, 6]
چون ما دیتای ی خونه دیگه از حافظه رم رو تغییر دادیم و فقط مقدار متغیری که به اون خونه اشاره میکنه تغییر کرد.
برای متوجه شدن این تفاوت میتونید با دستور زیر نتیجه رو ببینید:
print(id(list1))
print(id(list2))
print(id(list3))
تابع id آدرس خونهای که متغیر بهش اشاره میکنه رو میده، اینجا لیست یک و لیست دو ی چیز رو چاپ میکنن ولی لیست سه ی چیز دیگه رو چاپ میکنه.
حالا علامت == فقط مقدار دو تا متغیر رو با هم مقایسه میکنه ولی علامت is میاد هم مقدارشون و هم اینکه به ی خونه اشاره میکنن یا نه رو بررسی میکنه، پس:
list1 is list2 -> True
list1 == list2 -> True
list1 is list3 -> False
list1 == list3 -> False (البته چون اونجا ۶ رو به لیست سه اضافه کردیم)
قبل append
list1 == list3 -> True
این همون مفهوم (کپی سطحی)shallow copy در پایتونه.
روش اول کپی نکرد، بلکه آدرس خونه رم رو به متغیر دوم نسبت داد ولی دومی کپی سطحی کرد.
حالا فرض کنید لیست اول رو به این صورت تعریف کردیم:
list1 = [1, 2, [3, 4], 5]
یعنی ی لیست دیگه هم بعنوان ی آیتم بهش دادیم، یعنی بعبارتی لیست تو در تو ایجاد کردیم.
اینجا اگه از روش کپی سطحی استفاده کنیم بازم همون مشکل اول بوجود میاد؛ چون باز آدرس خونه رم لیست داخلی رو داد به متغیر دومی.
list2 = list1[:]
حالا فرض کنید تغییر رو بصورت زیر اعمال کردیم:
list2[2][0] = 9
دوباره خروجی لیست اول رو ببینید:
print(list1) -> [1, 2, [9, 4], 5]
چطور میتونیم جلوی این مشکل رو بگیریم و بعبارتی ی (کپی عمیق)deepcopy داشته باشیم؟
با استفاده از کتابخونه داخلی copy:
import copy
list2 = copy.deepcopy(list1)
البته میشه با همین کتابخونه هم ی کپی سطحی داشت، بصورت زیر:
list3 = copy.copy(list1)
سعی میکنم بیشتر درموردش صحبت کنم.
👍18🤮1
✅ مطلب مفیدی درباره Logging از کانال @PyHints
یک دوستی دیروز راجب لاگ نویسی توی پایتون سوال داشت من به اینصورت براش توضیح دادم گفتم شاید مفید باشه :
نشون میده هر دسته از لاگ رو چطور باید باهاش برخورد کرد بطور کلی ۵ دسته بندی برامون خیلی مهم هستندکه به ترتیب از محیط توسعه و اطلاعات بیشتر به سمت محیط پروداکشن و وضعیت خطرناک تر میریم :
نسخه روزانه فقط اطلاعات سطح
نسخه ماهانه اما جاهایی هست که
اما بطور کلی warning , … خطاهای نرم افزار رو لاگ میکنه مثلا اگر سرور ارور 500 برای کاربری فرستاد تحت چه شرایطی و به چه دلیل این اتفاق افتاده و …
توی اکثر سناریوها لاگ ها بعد از یک مدت بصورت اتوماتیک بررسی میشن و تحت شرایطی خاص به ادمین سرور یا توسعه دهنده یا … هشداری رو ارسال میکنند پس اینکه چه اطلاعاتی به چه صورتی نوشته بشه مهم هست و وظیفه
بعنوان مثال روی پروژههای مهم لاگهای سطح
بنظرم دونستن اهمیت این ۴ تا کامپوننت؛ برای لاگ نویسی از هرچیزی مهمتر هست.
@PyHints
یک دوستی دیروز راجب لاگ نویسی توی پایتون سوال داشت من به اینصورت براش توضیح دادم گفتم شاید مفید باشه :
Python logging components :وضعیت لاگ؛ همیشه لازم هست.
1- Loggers
نشون میده هر دسته از لاگ رو چطور باید باهاش برخورد کرد بطور کلی ۵ دسته بندی برامون خیلی مهم هستندکه به ترتیب از محیط توسعه و اطلاعات بیشتر به سمت محیط پروداکشن و وضعیت خطرناک تر میریم :
debug - info - warning - error - critical
معمولا روی محیط توسعه از debug
استفاده میکنیم و روی محیط پروداکشن شخصا ۲ تا نسخه نگه میدارم یک نسخه که روزانه پاک میشه (به این وضعیت اتومات حذف شدن هم logrotate
گفته میشه اصطلاحا) و یک نسخه هم که ماهانه rotate
میشه ولی تا ۱ سال گذشته رو نگهداری میکنیم. نسخه روزانه فقط اطلاعات سطح
info
رو نگهداری میکنه؛ بیشتر برای این نگهداری میکنیم که بدونیم چه کسی؛ چه زمانی؛ چیکار کرده ؟نسخه ماهانه اما جاهایی هست که
warning - error - critical
داشتیم؛ ی وقتایی ممکنه از لاگ info
برای warning
استفاده بشه : برای مثال ممکنه یک یوزر با رفتار امن شروع کنه به درخواست زیاد فرستادن به یکی از لاگین ها اینجا جایی هست که میشه لاگ info رو بررسی کرد و اطلاعات اون یوزر رو توی warning هم داشت اما بطور کلی warning , … خطاهای نرم افزار رو لاگ میکنه مثلا اگر سرور ارور 500 برای کاربری فرستاد تحت چه شرایطی و به چه دلیل این اتفاق افتاده و …
2- Formatters
از قدیم گفتن لاگ بدون فرمت بدرد صاحب کد هم نمیخوره؛توی اکثر سناریوها لاگ ها بعد از یک مدت بصورت اتوماتیک بررسی میشن و تحت شرایطی خاص به ادمین سرور یا توسعه دهنده یا … هشداری رو ارسال میکنند پس اینکه چه اطلاعاتی به چه صورتی نوشته بشه مهم هست و وظیفه
formatter
هم دقیقا همین هست. مثلا : warning sample.py unauthorized requests to resource at 2023-06-20 17:16:15 from 192.168.1.5 response code 401بطور کلی مشخص میکنه با هر پیام لاگی که میاد چیکار باید کرد ؟ اینکه برای info فایل جدا داشته باشیم یا یک سری از اطلاعات رو داخل کنسول / ترمینال نمایش بدیم و … توسط ایشون انجام میشه
3- Handlers
بعنوان مثال روی پروژههای مهم لاگهای سطح
critical
رو بصورت ایمیل یا پیامک برای چند شخص میفرستیم تا سریعتر بررسی بشه و این کار توسط Handler
انجام میشه 4- Filtersممکنه توی لاگ نویسی یک سری از اطلاعات محرمانه باشه و تحت هیچ شرایطی نباید توی لاگ بیاد مثلا توی مثال بالا ممکن بود من توی اطلاعات لاگ هم بگم که خب شماره موبایل کاربری که داره اینکار رو میکنه هم داشته باشیم اما قطعا بیزینس نمیخواد این اطلاعات توی لاگ هایی که آرشیو میکنه یا ممکنه به یک شرکت دیگری برای بررسی بده وجود داشته باشه پس در نهایت یک فیلتر مینویسه که برخی از این اطلاعات که محرمانه هستند حذف بشه یا با یک مقدار از پیش تعیین شده جایگزین بشه.
بنظرم دونستن اهمیت این ۴ تا کامپوننت؛ برای لاگ نویسی از هرچیزی مهمتر هست.
@PyHints
👍11🤮2