🧑‍💻PythonDev🧑‍💻
365 subscribers
86 photos
3 videos
15 files
78 links
Python tips and tricks
The Good, Bad and the Ugly

📚توی این کانال فقط قرار هست در مورد core python صحبت کنیم.

👨‍💻این کانال یک بلاگ شخصی هست و پیرامون نظرات و چیزهایی که توی این چند سال کد زدن یاد گرفتم (فقط برای کمک به دوستان تازه‌کار)👨‍💻


@Mtio975
Download Telegram
photo_2023-09-23_23-01-54.jpg
41.3 KB
این کد ی مشکل اساسی داره (بزرگ و اساسی) مخصوصا توی پروژه‌های حرفه‌ای
موضوع پیچیده‌ای نیست ولی چون زیاد دیدم ترجیح دادم بهش اشاره کنم تا کم کم دیگه نبینیم.

می‌تونید حدس بزنید چی هست ؟

توضیحات پست بعدی

پ.ن : typing توی پروژه‌ها موضوع مهمی هست اما توی پایتون الزامی نیست
هیچوقت باگ محسوب نمی‌شه و فقط جزو شرایط
clean code
هست (به این مورد اشاره نکنید)
🧑‍💻PythonDev🧑‍💻
photo_2023-09-23_23-01-54.jpg
مشکل اصلی استفاده از
except Exception as ex:
که دوستان توی کامنت اشاره کردند.

اصطلاحا به این روش میگن
Broader Approach

مسئله اینه که توی کد بالا من با ارور هیچ‌کاری نمیکنم (اما توی این شرایط هم broader approach اشتباه هست) ولی فرض کنید شما باید این موارد رو لاگ بندازید. در این شرایط exception handle شما به درد نمیخوره احتمالا لاگ هم همینطور چون کسی اروری نمی‌بینه که بخواد لاگ فایل رو بخونه (حتی اگر توی لاگ جزئیات بیشتری هم نوشته شده باشه)
منبع بسیاری از BUG های مخفی همین مورد هست.

قبل از اینکه راه حل رو بگم ی موضوع دیگه برای تازه‌کارها اشاره کنم (شوخی و روشی برای ایستگاه کردن junior developer ها بوده البته کمتر دیده می‌شه دیگه ولی ی زمان تو دانشگاها خیلی زیاد بود بخصوص خارج از ایران) شاید بخاطر اینکه دیگه این مدل کد استفاده نمی‌شه

ی مدل دیگه exception داریم که اصطلاحا بهش میگن :
naked exception
از همینجا شاید متوجه شدید دیگه؛ 😂😂

نوع تعریفش اینطوری هست :
except:

قبلا که خیلی مد بود استفاده ازین مورد و هنوز کلمه nude انقدر جاافتاده نبود برای ایستگاه کردن دانشجوهای سال پایینی استفاده میشد (بین‌المللی)
طرف به ارور میخورد بهش میگفتن ؛ naked ات رو بده تا بگم (خیلی وقتا کار به جاهای باریک میرسید مراقب باشید خلاصه 😅😅😅)

ازین ۲ مدل هیچوقت استفاده نکنید که یا BUG مخفی میخورید یا خدایی نکرده ایستگاه می‌شید.

راه حل کد بالا :
۲ تا Exception جدا بنویسید :
except IndexError as ex:
و اگر قرار هست TypeError هم silent کنید در ادامه‌اش
except TypeError as ex:

یا حتی ادغام هر ۲ :
except (IndexError, TypeError) as ex:
اینو همه‌ی سرمایه‌گذارهای پروژه و کد توی ایران حتما باید ببینند :
برای دولوپر‌های عزیز هم قبل از اینکه جوگیر بشید و بگید میخوام شرکت بزنم این رو ببینید (این بررسی فقط از جنبه‌های توسعه نرم‌افزار هست باقیش هیج)

https://www.youtube.com/watch?v=Dl-BdxNRUqs
کانفیگ logging برای من همیشه اذیت کننده هست.
بخش عمده‌ای از تسک‌های من مربوط میشه به
Deep learning, ML engineering

اما وجه دیگه کارم backend هست و software engineer برای همین خیلی کم پیش میاد نیاز داشته باشم ی لاگر با جزئیات بنویسم

از طرفی هم ۹۰٪ کدهایی که از بچه‌های بکند تحویل میگیرم ی logging نوشته شده که حافظه زیادی قرار هست بگیره (بخصوص روی سرور تست دارم صحبت میکنم که حجم لاگ بالا میره)

این کد رو قبلا برای Django نوشتم ؛ توضیح دادم تقریبا چند هفته بعد از شروع یادگیری یکی از بدترین پروژه‌های شرکت رو دست گذاشتم روش و شروع کردم به بازنویسی این لاگر رو برای اون نوشتم

هر لاگ فایل تا ۱۰ مگ حجم می‌تونه اشغال کنه و بعد از اون فایل ذخیره میشه به اسم backup تا ۱۰ تا ورژن ازین بکاپ‌ها نگه میدارم فقط و روی نسخه ۱۱
log rotate 
میخوره و قدیمی‌ترین فایل حذف میشه

البته این خیلی ساده‌اس ولی خب از اون کیلویی اضافه کردن logging فایل قطعا بهتره

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

۱- کد بالا ربطی به django نداره، هرچند توی یک خط من برای مسیر فایل از django استفاده کردم. Logging مربوط به core python هست.

۲- بیش از ۳۰ نفر سوالاتشون راجب همین موضوع بود، تماماً هم مشترک (دوستان گروه برای همین منظور ساخته شده و بخش کامنت) ازین به بعد این سوالات رو فقط توی گروه بپرسید.

۳- توی پیام‌ها ویس ندید، مخصوصاً قبل از هماهنگ کردن ۹۹.۹٪ اصلا پیام رو باز نمی‌کنم اگر اینطور باش

۴- احوال پرسی و خبر پرسیدن رو نمی‌فهمم، بعد حالا اگر پرسیدید چرا منتظر جواب نمی‌مونید ؟
بجای خوب هستی و چه خبر، همون سلام کفایت می‌کنه و یا اگر عادت کردید برای غریبه از
امیدوارم سلامت باشید استفاده کنید بخدا قشنگتر هم هست

۵- قبل از سوال پرسیدن نیازی به تاریخچه نویسی نداره، کی بودید و چیکار کردید و چرا به من ربطی نداره واقعاً و اگر برای راهنمایی لازم باشه قطعاً خودم می‌پرسم از شما (بعضی‌ها ۲۰ تا پیام میذارند آخر سوال از یکی از پست‌های کانال می‌پرسند)

۶- نهایتاً، خواهش می‌کنم
خواهش می‌کنم
اصلی ترین رفتار برنامه‌نویسی رو رعایت کنید

پیام‌ها رو مختصر بنویسید همه‌ی موارد رو داخل یک پیام ارسال کنید بریده بریده پیام دادن اسپم حساب می‌شه

بدتر از بریده بریده پیام دادن ۷-۸ تا پیام فرستادن و در نهایت گفتن این هست که بگید، می‌تونم سوال بپرسم ؟!

بجای اسپم کردن، اصل سوال رو بپرسید لطفاً این خیلی خیلی مهم هست.


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

مرسی از همگی دوستانی که رعایت می‌کنند یا خواهند کرد 🌹
ازین مدل کد توی سورس کد پکیج‌ها زیاد دیدید همون استاندارد
EAFP
امروز یکی از نیروهای junior که باهاشون کار می‌کنم روی یکی از کدها به اروری میخورد و کار پیش نمی‌رفت.
ارور فریمورک هم واقعا نامشخص نبود و چیزی ازش دستمون رو نمی‌گرفت (زمانی که tensorflow 0.7 اومده بود قشنگ یادم هست ازین چالش‌ها زیاد داشتیم)

توی سورس اگر کدهارو بخونید یک ساختاری شبیه عکس وجود داره که باعث میشه در نهایت ارور خاص فریمورک برگرده؛ البته با یک تغییر کوچیک توی خط 10 :
raise CustomException('Finally we raise our custom error in framework.') from None

همین from None باعث میشه exception های قبلی چاپ نشه.

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

دیدم نیروی خودم بلد نبود گفتم شاید بهتر باشه اینجا هم بذارم بدرد کسی بخوره.
حتما شما هم با with open توی پایتون کار کردید فوق‌العاده کمک کننده و مفید هست
همین که دیگه لازم نیست یادتون بمونه فایل رو ببیند یا اینکه کد درست رو بزنید
بستن فایل باید توی بخش finally باشه و ...
try:
excpet:
finally:

همین شرایط برای connection به دیتابیس هم هست.

with open

از یک راه حل تمیز و زیبا استفاده می‌کنه که بهش
Context Manager Protocol
گفته می‌شه
یک کلاس داخل تعریف پروتوکل
context manager 
قرار می‌گیره اگر ۲ تا متد رو داشته باشه

__enter__, __exit__

__enter__
دقیقا وقتی وارد بلوک
with .... :
pass

می‌شیه اجرا می‌شه و __exit__ وقتی از with خارج می‌شه
پس توی این بین میشه کارهای زیادی انجام داد

کد بالا مربوط به یکی از پروژه‌های بزرگ هست که توضیح میدم بدها
ی hot-fix که زدم و از print رو بجای logger استفاده کردم
توجه کنید خارج از with خروجی print مثل قبل چاپ میشه و دیگه توی فایلی نوشته نمیشه چون توی __exit__
sys.stdout
به مقدار قبلی برمیگرده.
کتاب django for beginners برای اون هایی که میخوان با جنگو شروع کنن میتونه یه کیک استارت خوب باشه
Django_for_beginners_Build_websites_with_python_and_django_DevTwitter.pdf
14.2 MB
#Django

Django for beginners
Build websites with python and django
By William S. Vincent

308 Pages
فایل بعدی که باید داشته باشید
requirements.txt
نبودش توی تیم ما خطای بزرگی هست :
۱- دیلی شرکت نکردن بدون اطلاع قبلی؛ دستمزد اون روز رو حذف می‌کنه
۲- پروژه تحویل دادن بدون
requirements.txt
درست بین ۲ تا ۷ روز کسر از دستمزد داره (اهمیت رو ببینید)

اما توی تیم من حداقل ۳ نکته هم باید رعایت بشه :
۱- بجای یک فایل باید ۳ تا فایل برای requirements داشته باشید
base.txt- local.txt - product.txt
یک پوشه به این اسم میسازید و این ۳ فایل داخلش قرار میگیره
تصویر بالا برای فایل
base.txt
هست؛ این فایل شامل پکیج‌هایی میشه که چه توی محیط توسعه چه توی پروداکشن باید وجود داشته باشه
local.txt
برای محیط توسعه هست خط اول این فایل همیشه باید
-r base.txt
باشه که بصورت اتومات پکیج‌های داخل base رو هم شامل بشه موقع نصب و باقی خط‌های فایل شامل پکیج‌هایی میشه که فقط توی محیط توسعه لازم هست :
black, isort,  flake8, pre-commit, ...
و در نهایت
prod.txt
مواردی که فقط روی پروداکشن لازم هست بازم خط اول باید
-r base.txt
باشه حتما و قطعا چیزی که توی local هست نباید اینجا باشه.
🧑‍💻PythonDev🧑‍💻
فایل بعدی که باید داشته باشید requirements.txt نبودش توی تیم ما خطای بزرگی هست : ۱- دیلی شرکت نکردن بدون اطلاع قبلی؛ دستمزد اون روز رو حذف می‌کنه ۲- پروژه تحویل دادن بدون requirements.txt درست بین ۲ تا ۷ روز کسر از دستمزد داره (اهمیت رو ببینید) اما توی…
۲- تمامی پکیج‌ها باید ورژن داشته باشند اما استفاده از
==
برای ورژن زدن پکیج‌ها ریکامند نمی‌شه بجاش از
~=
استفاده می‌کنیم دلیلش هم این هست که آپدیت‌های پچ رو بتونیم دانلود و نصب کنیم (چه امنیتی باشه چه رفع باگ‌های ساده) بدون اینکه نیازی به تغییر حتی ۱ خط کد باشه

۳- تا جایی که امکان داره موارد رو بصورت دستی بنویسید و از pip freeze دوری کنید؛ که فقط پکیج‌های اصلی ذکر بشه و فایل تمیزتری برای بررسی وجود داشته باشه.

این مواردی هست که توی تیم بنده رعایت می‌شه و تجربه بهم نشون داده کار خوبی هست (جاهای دیگه هم دیدم این مورد رو)
برخی از toml , ... استفاده می‌کنند که من برای پروژه تیمی تایید نمی‌کنم چون هرکسی ممکن ازین ابزارها استفاده نکنه ولی اگر کل تیم شما با اون فرمول پیش میره شما هم همون کار رو بکنید.

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

همیشه و تحت همه شرایط؛ خروجی Profiling رو ذخیره کنید اونم ۲ بار :
۱- قبل از اینکه کدی رو تغییر بدید (همیشه هم به اسمی ذخیره کنید که یادتون بمونه + تاریخ)
۲- بعد از اینکه تغییرات رو اعمال کردید (اسم تغییرات + تاریخ یا git commit)

شاید شما ندونید برای چی ذخیره می‌کنیم ولی ی روزی نجاتتون میده.

برای گرفتن خروجی بالا توی ترمینال این دستور رو اجرا می‌کنیم با توجه به این نکته که اسکریپت مثال (توی عکس قبلی رو به اسم example.py ذخیره کردیم)
python -m cProfile -s cumulative example.py
و درصورتی که بخوایم خروجی رو ذخیره کنیم که برای آنالیزش از
snakeviz, pstats
استفاده بشه و مهمتر از همه داکیومنتش کرده باشیم می‌تونیم از دستور
python -m cProfile -s cumulative -o compare_bubble_vs_builtin_sort_$(date +'%Y_%m_%dT%H_%M_%S').prof example.py

استفاده کنیم؛ حتما پسوند رو .prof بذارید که راحت شناسایی بشه.
🧑‍💻PythonDev🧑‍💻
قبل از اینکه خروجی cProfile رو تفسیر کنم می‌خوام مهمترین نکته توی زندگیتون موقع استفاده از ابزارهای profiling رو بگم. همیشه و تحت همه شرایط؛ خروجی Profiling رو ذخیره کنید اونم ۲ بار : ۱- قبل از اینکه کدی رو تغییر بدید (همیشه هم به اسمی ذخیره کنید که یادتون…
توی دستور بالا :
-m:
برای استفاده از یک ماژول خاص استفاده می‌شه
-s:
ترتیب نمایش هست که گفتیم بر اساس cumulative time باشه  همیشه هم همین رو استفاده خواهید کرد
-o:
برای اینکه خروجی رو توی یک فایل بریزه و توی ترمینال نمایش نده (اول در تاریخ ثبت می‌کنیم بعد ی بار هم بدون این option برای راحتی خودمون اجرا می‌کنیم)

تفسیر خروجیش هم خیلی ساده‌تر از اون چیزی هست که فکر می‌کنید فقط چندتا نکته داره :
ncalls:
تعداد فراخوانی اون خط از کد (ستون آخر کمی جلوتر توضیح میدم دقیق)
وقتی دوتا عدد هست مثل خط اول خروجی توی عکس قبلی
3/1:
عدد کوچیکتر تعداد فراخوانی غیر بازگشتی یا primitive هست و عدد بزرگتر تعداد کل فراخوانی به هر شکلی که بوده (بازگشتی و غیر بازگشتی و ...) یعنی بصورت کلی اون builtin method توی مثال قبل ۳ بار فراخوانی شده.

tottime:
مجموع زمان مورد نیاز جهت اجرای اون تایع؛ به غیر از زمان اجرای توابعی که داخل این تابع فراخوانی شده‌اند.

percall:
زمان اجرای مورد نیاز برای هربار اجرای اون خط یا اون تابع معمولا حدودی برابر هست با :
tottime / ncalls

cumtime:
مهمترین ستون همینه و اون مرتب سازی که توی دستور انجام دادیم (منظورم s cumulative- هست) بر اساس همین ستون بود.
مجموع زمان مورد نیاز از لحظه فراخونی اون خط یا تابع تا خروج از اون خط یا تابع + زمان مورد نیاز برای اجرای توایعی که داخل این تابع یا خط فراخوانی شدند + زمان اجرا بصورت recursive , ... خلاصه همه چیز اینجاس و از همه ستون‌ها هم دقیق‌تر هست

filename:lineno(function)
اینم که بسیار واضح هست از سمت چپ به راست :
اسم اسکریپت : شماره خطی که اون کد اجرا شده (اسم تابع)
اسم تابع برای شرایطی مهم هست که داخل تابع اصلی توابع دیگری هم فراخوانی بشه

توی خروجی بالا مواردی مثل builtin.exec (از توابع مورد علاقه من هست اصن ی وضعی) و برخی موارد دیگر برای
import random
هست


همینجا بگم که تصویر قبلی خروجی کامل cProfile نیست و بنده این خروجی رو بریدم تا خواناتر باشه
خوب از کجا شروع کنم براتون توضیح بدم همین چند دقیقه پیش داشتم با یه سری دوستان گفتگو میکردم در مورد بازار کار و اینکه برای بازار کار اماده هستن یا نه یه سری از دوستان میدونم پایتون کار کردن و جنگو هم خیلی کار کردن کلس داکیومنت خوندن و دوره مختلف دیدن و پروژه های مختلف زدن و کتاب های مختلفی هم خوندن ولی مثلا ویدیو وقتی میبینن مثل یوتیوب میکرو فرانت بر میخورن خیلی مباحث جدید می بینن مصاحبه هم که میرن رد میشن
🧑‍💻PythonDev🧑‍💻
خوب از کجا شروع کنم براتون توضیح بدم همین چند دقیقه پیش داشتم با یه سری دوستان گفتگو میکردم در مورد بازار کار و اینکه برای بازار کار اماده هستن یا نه یه سری از دوستان میدونم پایتون کار کردن و جنگو هم خیلی کار کردن کلس داکیومنت خوندن و دوره مختلف دیدن و…
در ادامه این باید بهتون بگم که اول بررسی که دوره ها رو پروژه ها ور کتاب های که خوندی نرو سطح مهارت های خودت رو ارزیابی کنید ببینید میتونید مفاهیم پیچیده رو درک کنی و تو کاربرد عملی ازشون استفاده کنید اگهی های استخدامی رو مطالعه کنید تو همون حوزه جنگو تحلیل کنید نیاز های موجود تو بازار ر و بهتون کمک میکنه که کدوم موضوع ها کمی ناکافی هستن و چه مهارت های رو هم باید بهبود بدین مهارت های جدید رو بررسی کنید ویدیو ها و منابع اموزش میکرو فرانت اند رو بررسی کنید یا هر موضوع جدید دیگه ای رو یا هر موضوعی که بهش برخورد میکنید رو ببینید اینکه میتونید این موضوع ها رو یاد بگیرید یا نه که این بستگی به نیاز شغلی خودتون داره از مصاحبه ها بازخورد بگیرین اگه خدای نکرده تو مصاحبه رد شدین سعی کنید از مصاحبه کننده یه بازخورد بگیرید این بهتون کمک میکنه نقطه ضعف خودتون روپیدا کنید مهارت های جدید رو توسعه بدین برنامه ریزی واسه توسعه دادن یه مهارت جدید و پیشرفت تو حوزه های که الان نیاز مند بازار کار هستن این هم ممکن هستش که یه سری مهارت های اضاف مثل فرانت اند یا مدیریت پروژه هم براتون مفید باشه تمام مورادی که براتون بهش گفته هم بر گرفته از تجریات کاری خودم هستش و بهتون گفتم که تو مسیر کار و یادگیری به مشکل برنخورید
خیلی وقتا بهم میگن، اشتباه می‌کنی و وقتت رو الکی تلف می‌کنی که بجای خوندن فقط آموزش و یادگیری میری سورس کد رو میخونی ؛

هیچ‌وقت این موضوع رو جواب نمیدم و همیشه می‌گم حق با شماست، ولی به این آدما باید گفت :

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

حداقلش : کمک واضح به
System design, Optimization
هست.

مثلاً می‌دونستید
Coroutine
توی پایتون 3.5 کلا ۳۵۰ خط کد بوده، و پیاده سازیش با
generator
های پایتون بود ؟
برای همین می‌تونستیم خیلی راحت بهش فیچر اضافه کنیم (کاری که توی پروژه انجام دادیم)

تصویر مربوط به سورس کد coroutine روی python3.5
🧑‍💻PythonDev🧑‍💻
خیلی وقتا بهم میگن، اشتباه می‌کنی و وقتت رو الکی تلف می‌کنی که بجای خوندن فقط آموزش و یادگیری میری سورس کد رو میخونی ؛ هیچ‌وقت این موضوع رو جواب نمیدم و همیشه می‌گم حق با شماست، ولی به این آدما باید گفت : خیلی باید رشد کنی، تا بفهمی چرا حتماً باید بعضی سورس…
حالا ی بحثی که پیش میاد این هست که چقدر باید سورس کد خوند و تا کجا ؟

اینکه هر پکیجی که دستمون میاد رو بریم سورس کدش رو بخونیم که عملاً واقعی نیست، کاش سرعت خوندن انقدر زیاد بود یا زمان زیادی داشتیم که خب اینطوری نیست و همین شاید زندگی رو ارزشمند کرده 🤔

ولی شخصاً مطالب و فیچرهای خیلی مهم پایتون رو حتماً سورس کداش رو میخونم (قرار نیست خط به خط دیباگ کنید)
باقی پکیج‌ها هم فقط مواردی که می‌دونم ازون روزی که یاد میگیرم به بعد قرار هست توی تموم پروژه‌هام ازش استفاده کنم و پول در بیارم

پکیج‌هایی که قراره فقط ۶ ماه باهاش کار کنم یا در حد ۱ پروژه هست رو هیچوقت اینکارو نمی‌کنم مگر اینکه مجبور بشم یا شرکت بخواد داخلش تغییرات ایجاد کنه.

این مرز بندی بسیار بسیار مهم هست که درست و بهینه باشه
دوستان که تازه کار هستن یه آمار بهم بدین بینم چی به چیه تا بنده براتون در مورد دوره های آموزشی و بازار کار براتون توضیح بدم
Anonymous Poll
62%
مبتدی(تازه کار)
24%
متوسط (کارآموزی)
14%
پیشرفته
یه سری از دوستان از من خواستن که در مورد یادگیر پایتون و اینکه مسیر اموزش پایتون و بازار کارش بگم خوب من سعی میکنم خیلی کامل توضیح بدم که کم گذاشته نباشم واستون و بهتون تو مسیر یادگیری کمک کنه خوب اول که باید بهتون بگم که واسه یادگیری پایتون مفاهیم اولیه رو اول یاد بگیرید مفاهیم اولیه شامل همون متغییر ها لیست حلقه و توابع میشه می تونید از منابع اموزشی انلاین استفاده کنید و یا کتاب های مانند learn python the hard way که نویسنده اون zed shaw هست استفاده کنید در مرحله دوم یادگیری ساختار داده ها و الگوریتم ها خیلی مهم هست که توی حل مسائل پیچیده خیلی به کارتون میاد از کتاب های که میتونم معرفی کنم میتونم به کتاب data structures and algorithms in python که اثر michael استفاده کنید و اینکه باید بگم که پروژه های عملی هم خیلی بهتون کمک میکنه بهترین روش برای تقویت مهارت های پایتون انجام داده پروژه های عملی هستش شروع به پیاده سازی پروژه های کوچک کنید مثل یک برنامه ماشین حساب یا یک برنامه تحت وب ساده و پس از این ها پروژه های پیشرفته تر مثل مدیریت سیستم داده ها بپردازین