<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های امیر اسمعیلی</title>
        <link>https://virgool.io/feed/@amiresm17</link>
        <description>دانشجوی مهندسی کامپیوتر و برنامه نویس فول-استک</description>
        <language>fa</language>
        <pubDate>2026-06-28 00:01:07</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/38394/avatar/1otBnb.png?height=120&amp;width=120</url>
            <title>امیر اسمعیلی</title>
            <link>https://virgool.io/@amiresm17</link>
        </image>

                    <item>
                <title>از اکسپشن ها فرار نکنید - نگاهی به ساختار اکسپشن‌ها در پایتون</title>
                <link>https://virgool.io/@amiresm17/%D8%A7%D8%B2-%D8%A7%DA%A9%D8%B3%D9%BE%D8%B4%D9%86-%D9%87%D8%A7-%D9%81%D8%B1%D8%A7%D8%B1-%D9%86%DA%A9%D9%86%DB%8C%D8%AF-%D9%86%DA%AF%D8%A7%D9%87%DB%8C-%D8%A8%D9%87-%D8%B3%D8%A7%D8%AE%D8%AA%D8%A7%D8%B1-%D8%A7%DA%A9%D8%B3%D9%BE%D8%B4%D9%86-%D9%87%D8%A7-%D8%AF%D8%B1-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-fbeam0ujpgvn</link>
                <description>مقدمهکد ها بسیار آسیب پذیر و شکننده هستند!قطعا دلچسب خواهد بود اگر همیشه بتوانیم نتایج دلخواه را از برنامه ها و اسکریپت‌هایی که نوشته‌ایم بگیریم، اما همیشه اینطور نیست. عملا نرم افزار می تواند در مقابل ورودی‌های نامناسب و محیط‌های نامناسب کاملا آسیب پذیر و شکننده باشد. برنامه‌ها سعی می‌کنند خطا‌ها و اشکالات پیش آمده را به نحوی به کاربر اطلاع دهند و برنامه نویس می بایستی تک تک آنها را کنترل کند. ولی خب خیلی‌ها این زحمت را به خودشان نمی‌دهند.در این مقاله قصد داریم تا به اکسپشن‌ها در زبان پایتون بپردازیم و نحوه صحیح استفاده از آن‌ها را درک کنیم. مفاهیمی‌ که می‌آموزیم:اکسپشن چیستچگونه یک اکسپشن raise کنیمنحوه برخورد با اکسپشن‌هاساختار اکسپشن‌هانوشتن یک اکسپشن جدیدبا اکسپشن‌ها آشنا شویدخب؛ در ابتدا بهتر است با ماهیت اکسپشن‌ها آشنا شویم. اکسپشن‌ها درواقع یک آبجکت ( Object ) هستند. پایتون چندین کلاس اکسپشن آماده دارد که شاخصه مشترک آن‌ها ارث بری از یک کلاس داخلی پایتون به نام BaseException است.عاملی که اکسپشن‌ها را مخصوص می‌کند این است که وقتی یکی از آن‌ها رخ می‌دهد کل اجرای برنامه متوقف می‌شود و صرفا قسمتی که برنامه نویس مشخص کرده اجرا می‌شود و یا به سادگی برنامه به اتمام می‌رسد. حالا چگونه یکی از آن‌ها را ببینیم؟ راحتترین روش اینه که یه کار احمقانه بکنیم :))مثلا یکی از اکسپشن‌هایی که مطمئنا همه با آن آشنا هستیم Syntax Error هست وقتی یک جای کد را اشتباه می‌نویسیم ( در این قسمت از پایتون ۳ استفاده شده است، اگر از پایتون ۲!!! استفاده می‌کنید خط پایین کار میکند ).Syntax Errorاین یکی از اکسپشن‌های خاص است، چرا که نمی‌توانید آن‌را کنترل کنید و حتما باید ایراد کد را درست کنید. حالا چند نمونه از اکسپشن‌هایی که می‌توان آن‌ها را کنترل کرد را ببینیم.چند نمونه اکسپشنهمیشه اکسپشن‌ها به معنی ورودی اشتباه نیستند، مثلا اکسپشن ZeroDivisionError را در نظر بگیرید‌ ( وقتی رخ می‌دهد که بخواهید یک عدد را بر ۰ تقسیم کنید )، ممکن است کاربر عدد ۰ را بخاطر صفر بودن موجودی حساب خود وارد کند یا بخواهد برای اینکه بتواند نرم افزاری را دانلود کند در صفحه donation مقدار صفر را وارد کند.اگر به تصویر بالا دقت کرده باشید، متوجه خواهید شد که همه اکسپشن های داخلی پایتون به Error ختم می‌شوند. در پایتون exception و error به‌جای هم استفاده می‌شوند، اما یک تفاوت بسیار کوچک دارند. error ها همگی از کلاس Exception ارث بری می‌کنند که آن نیز از کلاسی که قبلا مطرح شد یعنی BaseException ارث بری می‌کند.یک اکسپشن نشان دهید !وقت آن رسیده که یک اکسپشن تولید کنیم ( برای تولید اکسپشن از اصطلاح Raise استفاده می‌شود ).def factorial(number):
    if not isinstance(number, int):
        raise TypeError(f&amp;quotCannot calculate factorial for {type(number)}&amp;quot)
    if number &lt; 0:
        raise ValueError(&amp;quotThe number must be &gt;= 0&amp;quot)
    if number == 0 or number == 1:
        return 1
    else:
        return number * factorial(number - 1)در این تابع ساده که وظیفه محاسبه فاکتوریل یک عدد را دارد، اگر number عدد صحیح نباشد اکسپشن از نوع TypeError ایجاد می‌شود. در if بعدی اگر عدد کوچکتر از صفر باشد ValueError رخ می‌دهد و در نهایت مقدار فاکتوریل محاسبه می‌شود.قبلا هم ذکر شد که اکسپشن ها آبجکت هستند، در هنگام ایجاد یک اکسپشن جدید می‌توانیم آرگیومنت‌هایی را به کلاس اکسپشن‌ بدهیم. مثلا رشته &quot;The number must be &gt;=0&quot; یک آرگیومنت برای کلاس ValueError می‌باشد. این آرگیومنت‌ها می‌توانند هنگام مدیریت اکسپشن‌ها اطلاعات مفیدی به کاربر بدهند. نحوه استفاده از این آرگیومنت‌ها را در بخش های بعدی خواهیم دید. این قطعه کد را در فایلی ذخیره کنید سپس در ترمینال خود دستور زیر را وارد کنید.$ python[3] -i factorial.py
# نام فایل factorial.pyاین دستور فایل factorial.py را داخل interpreter پایتون import میکند و می‌توانید از تابع factorial استفاده کنید.استفاده از تابع factorialاکسپشن دقیقا چه کاری انجام می‌دهد؟!وقتی یک اکسپشن رخ می‌دهد، خط‌های بعد از وقوع اکسپشن دیگر اجرا نمی‌شود و اگر برنامه نویس اکسپشن به‌وجود آمده را مدیریت نکند برنامه با یک پیغام خطا متوقف می‌شود. برای درک بهتر موضوع دو تابع زیر را در نظر بگیرید.# exception-path.py

def exception_sample():
    print(&amp;quotHere is an exception&amp;quot)
    raise Exception(&amp;quotThis will happen all the time&amp;quot)
    print(&amp;quotHi&amp;quot)
    print(&amp;quotNo response ?&amp;quot)

def executor():
    print(&amp;quotExecutor started&amp;quot)
    exception_sample()
    print(&amp;quotExecutor ended&amp;quot)$ python3 -i exception-path.pyتابع اول را اجرا کردیم. همانطور که می‌بینید پرینت اول اجرا شده ولی سپس اکسپشن ایجاد شده است و خطوط بعدی رها می‌شوند.حالا تابع دوم را اجرا کردیم. پرینت اول تابع اجرا شده سپس پرینت تابع فراخوانی شده نیز اجرا می‌شود ولی به محض رخدادن اکسپشن روند برنامه ( هردو تابع ) متوقف می‌شود و برنامه خارج می‌شود. این ویژگی جالب اکسپشن ها است که مهم نیست در کجا رخداده باشند، برنامه در همان نقطه متوقف نمی‌شود، بلکه تا ابتدایی ترین مرحله بالا می‌آید تا به برنامه نویس فرصت دهد تا در محل مناسب وقوع اکسپشن را مدیریت کند. به تصویر بالا دقت کنید. زیر Traceback مسیر کامل پیموده شده توسط اکسپشن نشان داده شده است. از ماژول مورد نظر تا تابع اولیه سپس تابع دوم ، ... تا شماره خط رخ دادن اکسپشن.یک اکسپشن شکار کنید!وقت آن رسیده است که اکسپشن‌ها را شکار کنیم D: . برای اینکه بتوانیم اکسپشن ها‌ را مدیریت کنیم آن قسمت از کد که احتمال رخدادن اکسپشن در آن قسمت وجود دارد را باید داخل بلوک try بنویسیم و بعد از آن می بایستی عملیاتی که می‌خواهید هنگام بوجود آمدن اکسپشن اجرا شود را داخل بخش except پیاده سازی کنیم. ساختار کلی بلوک try except را در زیر ببینید.try:
    do_something()
except [Exception]:
    do_something_else()تابع executor از قسمت قبل را به یاد دارید. به اینصورت آن را تغییر می‌دهیم.def executor():
    print(&amp;quotExecutor started&amp;quot)
    try:
        exception_sample()
    except Exception:
        print(&amp;quotCaught an exception&amp;quot)
    print(&amp;quotExecutor ended&amp;quot) خروجی اجرای این تابع:اکسپشن مدیریت شده است.در این تابع خط اول اجرا شده سپس تابع exception_sample داخل یک بلوک try اجرا می‌شود و هنگام مشاهده اکسپشن کد‌های داخل بلوک except اجرا می‌شود. به کلاس مقابل except دقت کنید؛ در این بلوک except تمام اکسپشن ها ( بجز دو مورد خاص که بعدا بحث می‌شوند ) مدیریت می‌شوند و برای تمامی کلاس ها یک رفتار پیاده سازی شده است. گاهی نیاز است که برای کلاس‌های مختلف رفتار‌های متفاوتی معین شود مثلا اگر کاربر بجای عدد، یک رشته به عنوان آرگیومنت به تابع داد ارور شماره ۱ برای کاربر چاپ شود و اگر عدد منفی داد ارور شماره ۲. این کار به آسانی قابل اجرا است، فقط کافی است بجای Exception نام کلاس مورد نظر را بنویسید؛ مثلا IndexError. ساختار کد شما به شکل زیر خواهد بود.try:
    print(my_list[10])
except IndexError:
    print(&amp;quotThe provided index is not available&amp;quot)همچنین می‌توانید چند کلاس مختلف پشت سر هم مدیریت کنید.try:
    do()
except Class1:
   do_for_class1()
except Class2:
   do_for_class2()
except Class3:
   do_for_class3()قبلا اشاره شد که اکسپشن‌ها می‌توانند مقادیری را به عنوان argument دریافت کنند. در هنگام مدیریت اکسپشن‌ها دسترسی به این مقادیر می‌تواند کمک بزرگی به کاربر برای اشکال یابی بکند. کلیدواژه as این امکان را به ما می‌دهد که اکسپشن را به عنوان یک متغیر ذخیره و به اطلاعات آن دسترسی پیدا کنیم. این قابلیت زمانی بهتر دیده می‌شود که ما اکسپشن های خودمان را تعریف کنیم. فعلا به این حد بسنده می‌کنیم تا در ادامه واضح تر و جزئی تر بحث کنیم.try:
   raise ValueError(&amp;quotThis is an argument&amp;quot)
except ValueError as e:
   print(&amp;quotThe exception arguments were&amp;quot, e.args)بصورت قراردادی آبجکت اکسپشن‌ها را با e نمایش می‌دهند. اگرچه شما می‌توانید هر اسمی که مدنظرتان است استفاده کنید.آشنایی با Finally و Elseدر مبحث اکسپشن‌ها دو کلیدواژه finally و else بسیار با اهمیت هستند. در این بخش بصورت عملی با هرکدام آشنا خواهیم شد.کلیدواژه finally به برنامه نویس این امکان را می‌دهد که در هرصورتی ( چه اکسپشن رخ دهد، چه رخ ندهد ) بتواند یک کار خاصی را انجام دهد. فرض کنید شما مسئول برنامه نویسی یک دستگاه خودپرداز هستید، کاربر می‌خواهد از حساب خود پول برداشت کند. حال ممکن است کاربر به اندازه درخواستش پول در حساب داشته باشد یا خیر، ما می خواهیم بعد از دریافت پول یا مشاهده کسری موجودی، کارت از دستگاه خارج شود. اینجاست که finally به کمک ما می آید. عملیات برداشت را داخل بلوک try انجام دهید. اکسپشن کمبود موجودی را داخل بلوک except مدیریت کنید و درنهایت در بخش finally دستور خروج کارت را صادر کنید.def withdraw(amount):
    try:
        pay_money(amount)
    except LowBalance:
        print(f&amp;quotYou don&#039;t have {amount}&amp;quot)
    finally:
        take_out_card()در این قسمت تابع withdraw وظیفه پرداخت پول را برعهده دارد. ابتدا تابع pay_money فراخوانی می‌شود ( فرض کنید این تابع قرار است موجودی را چک کند و اگر موجودی به اندازه کافی بود پول پرداخت شود. در غیر اینصورت اکسپشن LowBalance را ایجاد کند ). در صورت رخ دادن اکسپشن مورد نظر پیغام خطا چاپ می‌شود و در نهایت بعد از دریافت پول یا مشاهده پیفام خطا، در بخش finally کارت خارج می‌شود.نکته: اکسپشن LowBalance جز اکسپشن های داخلی پایتون نیست و خودمان تعریف کرده ایم. در ادامه روش تعریف اکسپشن‌های جدید را خواهیم دید.کلیدواژه else را مطمئنا در شرط‌ها ( if ) دیده اید، اینجا نیز کارکردی تقریبا مشابه دارد. else در واقع به برنامه نویس اجازه می‌دهد اگر هیچ اکسپشنی رخ نداد کاری را انجام دهد. به تفاوت else و finally دقت کنید. اولی فقط در صورتی که هیچ اکسپشنی رخ ندهد اجرا می‌شود اما دومی در هر صورت. حالتی را فرض کنید که در یک قطعه کد try, except هم else داریم و هم finally، در این صورت اگر اکسپشنی رخ ندهد، هم محتوای داخل else اجرا خواهد شد هم محتوای داخل finally. مثال زیر روش استفاده از else را نشان می‌دهد.try:
    do()
except Exception:
    handle_exception()
else:
    no_exception()حالا که کلیات مدیریت اکسپشن‌ها را یادگرفتیم، بیایید با یک مثال این مطالب را تثبیت کنیم.# structure.py

import random
some_exceptions = [ValueError, TypeError, IndexError, None]
try:
    choice = random.choice(some_exceptions)
    print(&amp;quotraising {}&amp;quot.format(choice))
    if choice:
        raise choice(&amp;quotAn error&amp;quot)
except ValueError:
    print(&amp;quotCaught a ValueError&amp;quot)
except TypeError:
    print(&amp;quotCaught a TypeError&amp;quot)
except Exception as e:
    print(&amp;quotCaught some other error: %s&amp;quot % ( e.__class__.__name__))
else:
    print(&amp;quotThis code called if there is no exception&amp;quot)
finally:
    print(&amp;quotThis cleanup code is always called&amp;quot)قطعه کد بالا در هر مرحله اجرا از لیست some_exceptions یک اکسپشن یا None را انتخاب می‌کند. سپس با توجه به اینکه مقدار انتخاب شده از نوع اکسپشن می‌باشد یا نه، سعی می‌کند آن را مدیریت کند. چندبار این قطعه کد را اجرا کنید. به ساختار کد هم توجه کنید. همیشه باید اول try بعد except سپس else و در نهایت finally تعریف شود.# If IndexError
raising &lt;class &#039;IndexError&#039;&gt;
Caught some other error: IndexError
This cleanup code is always called

# If ValueError
raising &lt;class &#039;ValueError&#039;&gt;
Caught a ValueError
This cleanup code is always called

# If TypeError
raising &lt;class &#039;TypeError&#039;&gt;
Caught a TypeError
This cleanup code is always called

# If None
raising None
This code called if there is no exception
This cleanup code is always calledتا اینجای کار توانستیم اکسپشن‌ها را مدیریت کنیم و بدون خطر خاصی به ادامه برنامه بپردازیم. ولی همیشه اینطور نیست، گاهی یک حرکت مخرب از سمت کاربر ممکن است برنامه را به سمت اشتباهی ببرد ( حتی با وجود try, except ). در این صورت می‌خواهیم بعد از اینکه اکسپشن هندل شد دوباره همان اکسپشن ایجاد شود و با نمایش پیغام خطا برنامه متوقف شود. این حالت را در نظر بگیرید که برنامه شما برای اجرا شدن نیاز به یک پایگاه داده دارد ( اگر با فریمورک‌هایی مثل جنگو آشنا هستید این سناریو برایتان روشن است ). حال شما برنامه را آغاز می‌کنید ولی مثلا فایل پایگاه داده موجود نیست یا پایگاه داده روی پورت 5432 ( پورت پیشفرض پستگرس ) فعال نیست. در اینصورت مدیریت اکسپشن تاثیری در روند کار نخواهد داشت، چرا که تا وقتی پایگاه داده متصل نباشد کلیه فرایند‌ها به مشکل برخواهند خورد. پس تصمیم می‌گیریم پس از catch کردن اکسپشن چند نمونه راهنما برای کاربر چاپ کنیم و در نهایت با فعال کردن همان اکسپشن برنامه را خاتمه بدهیم.try:
    connect_to_database()
except DataBaseNotFound:
    print(&amp;quotMake sure to configure your setting file or check if database exists&amp;quot)
    raiseساختار کلی کد کاملا مشابه هرآنچه تا الان دیدیم است. تنها چیز متفاوت وجود raise می باشد. کلیدواژه raise بدون نوع کلاس، اکسپشنی که رخ داده است را دوباره فعال می‌کند. اگر کد بالا برایتان واضح نیست به مثال پایین دقت کنید.my_list = [1, 2, 3, 4]
try:
    print(my_list[10])
except IndexError:
    print(&amp;quot Be careful !!! &amp;quot)
    raiseخروجی کد بالا به شکل زیر است.سلسه مراتب در اکسپشن‌هادر بخش‌ها قبل در مورد اکسپشن‌ها و مدیریت آن‌ها صحبت کردیم. حال بیایید عمیق‌تر وارد این مبحث شویم. قبلا گفته شد تمامی اکسپشن‌ها از یک کلاس به نام Exception ارث بری می‌کنند که آن کلاس نیز از BaseException ارث بری می‌کند. همچنین گفته شد اکسپشن‌هایی که در انتهای نام خود واژه Error را دارند از Exception ارث بری کرده اند. دو کلاس اکسپشن در زبان پایتون وجود دارند که مستقیما از BaseException ارث بری کرده اند. SystemExit و KeyboardInterrupt. به ترتیب به توضیح هرکدام می‌پردازیم.اکسپشن SystemExit زمانی رخ می‌دهد که برنامه به صورت کاملا طبیعی خارج شود مثلا زمانی که دستور sys.exit یک جایی از کد اجرا شود‌ (مثلا کاربر از منو روی دکمه ضربدر برای خروج را کلیک می‌کند). هدف از طراحی این اکسپشن این بوده است که به ما اجازه بدهد قبل از خروج از برنامه اگر نیاز داریم کاری را انجام دهیم. مثلا بتوانیم قبل از خروج فایل هایی که توسط برنامه باز کرده ایم را ببندیم یا اگر فایلی ذخیره نشده آن را ذخیره کنیم. مورد بعدی KeyboardInterrupt می باشد که در برنامه های خط فرمان همگی با آن سر و کار داشتیم. وقتی یک برنامه پایتون را اجرا می‌کنید ولی قبل از اتمام برنامه دو کلید کنترلی Ctrl+C را می‌زنید، این اکسپشن raise می‌شود و برنامه متوقف می‌شود. همانند SystemExit این اکسپشن نیز قابل کنترل می باشد تا اگر می‌خواهیم قبل از بستن برنامه فعالیت نهایی برنامه را اجرا کنیم.با توجه به توضیحات داده شده می‌توان کلاس دیاگرام زیر را برای اکسپشن ها در پایتون رسم کرد.ساختار سلسه مراتبی اکسپشن هادر قسمت مدیریت اکسپشن ها بیان شد که except Exception  بجز دو مورد بقیه اکسپشن ها را catch می‌کند. این دو مورد همان SystemExit و KeyboardInterrupt هستند. احتمالا دلیلش را فهمیده اید. دقیقا؛ این دو مورد مستقیما از BaseException ارث بری می‌کنند. لذا از نوع Exception نیستند. متفاوت بودن ساختار این دو مورد با بقیه اکسپشن ها این امکان را به ما می‌دهد که با except Exception خطاهای احتمالی برنامه را مدیریت کنیم و مستقیما با این دو نوع اکسپشن ارتباط برقرار نکنیم.حالا که با ساختار اکسپشن‌ها آشنا شدیم بهتر است موارد زیر را ببینیم.except ValueError -&gt; فقط برای این نوع اکسپشن
except (IndexError, TypeError): -&gt; برای این دونوع اکسپشن
except Exception -&gt;  برای همه اکسپشن ها  بجز  دو مورد استثنایی
except -&gt; همه اکسپشن هااکسپشن های جدید!حالا بیایید یک اکسپشن جدید بنویسیم. برای نوشتن یک اکسپشن جدید کافی است فقط یک کلاس بسازید و از Exception ارث بری کنید. به همین راحتی:class SimpleException(Exception):
    pass
raise SimpleException(&amp;quotMy Simple Exception&amp;quot)می‌توانیم اکسپشن ها را گسترش بدهیم.class WeirdOddNumber(Exception):
    def __init__(self, number):
        super().__init__(f&amp;quotI don&#039;t like {number}&amp;quot)
        self.number = number
    def explain(self):
        print(f&amp;quotI don&#039;t like odd numbers and {self.number} is odd&amp;quot)جالب شد ! D:به تصویر زیر دقت کنید. پیاده سازی WeirdOddNumber و یک تابع که فقط اعداد زوج را چاپ می‌کند موجود می‌باشد. در انتها نیز سعی کرده ایم ۱۰ و ۱۳ را چاپ کنیم.اکسپشن های شخصی سازی شدهخروجی کد بالاعدد ۱۰ بدون مشکل چاپ شد. وقتی عدد ۱۳ را به print_even_numbers دادیم، تابع متوجه شد که این عدد فرد است پس اکسپشنی که تعریف کرده بودیم را raise کرد. خوشبختانه ما WeirdOddNumber را کنترل کرده بودیم. پس در بلوک except آرگیومنت آن یعنی ( I don&#x27;t like this 13 ) چاپ شد، سپس متد explain فراخوانی شد.سخن نهاییاز اکسپشن‌ها فرار نکنید؛ ممکن است با خود بگویید که همه حالات را ‌می‌توان با شروط مختلف بررسی کرد و از بروز اکسپشن‌ها جلوگیری کرد. اما مثلا ممکن است برای دسترسی به یکی از عناصر لیست، در ابتدا بررسی کنید که index داده شده حتما کمتر از طول لیست باشد اما یادمان نباشد که از وارد کردن اعداد منفی فراتر از حد لیست جلوگیری کنیم ( همانطور که می‌دانید در پایتون امکان دسترسی به لیست با index منفی وجود دارد ). این حالت جز یکی از ساده ترین حالات ممکن است. اما همیشه مسئله آنقدر ساده نیست. جدا از کنترل روند برنامه، استفاده از اکسپشن ها باعث افزایش خوانایی کد و درک بهتر آن می‌شود.برای نوشتن این مقاله از فصل ۴ کتاب Python3 Object Oriented Programming نوشته Dusty Phillips استفاده شده است.امیدوارم که این مطلب برایتان مفید واقع شده باشد. با سپاس.</description>
                <category>امیر اسمعیلی</category>
                <author>امیر اسمعیلی</author>
                <pubDate>Fri, 05 Mar 2021 23:05:04 +0330</pubDate>
            </item>
                    <item>
                <title>کبرا برای گو ! کتابخانه ای برای ایجاد برنامه های خط فرمان</title>
                <link>https://virgool.io/@amiresm17/%DA%A9%D8%A8%D8%B1%D8%A7-%D8%A8%D8%B1%D8%A7%DB%8C-%DA%AF%D9%88-%DA%A9%D8%AA%D8%A7%D8%A8%D8%AE%D8%A7%D9%86%D9%87-%D8%A7%DB%8C-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%87%D8%A7%DB%8C-%D8%AE%D8%B7-%D9%81%D8%B1%D9%85%D8%A7%D9%86-z2jmo6ko0b8a</link>
                <description>cobra
مقدمهبعضی وقت ها فقط می خواهیم یک فرآیند را خودکار کنیم، خیلی ها حوصله درگیر شدن با رابط کاربری را ندارند یا فقط دنبال آن هستند که سریعتر به نتیجه برسند، اینجاست که شما باید به فکر یک CLI باشید. یک برنامه خط فرمان که کارتان را راه بیندازد.سرعت فوق العاده و امکانات بالای زبان GO در چند سال اخیر باعث شده برنامه نویس های بیشتری به این زبان علاقه مند شوند، از این رو هرروز با افزایش جامعه گولنگ، کتابخانه ها و پکیج های متنوعی برای این زبان منتشر می شود. گو بخاطر کامپایل سریع و کراس-پلتفرم بودن پتانسیل بالایی برای اپلیکیشن های خط فرمان دارد، از این رو میخواهیم یکی از کتابخانه های مطرح در این حوزه را به صورت مختصر معرفی بکنم.کبرا ( Cobra )کبرا (Cobra) کتابخانه ای برای ایجاد برنامه های خط فرمان ( CLI ) می باشد که برای زبان گو به صورت متن باز منتشر شده است. کبرا نه تنها به شما کمک می کند تا یک اپلیکیشن خط فرمان بنویسید بلکه یک انتزاع کلی ( Abstract ) از ساختمان اپلیکیشن در اختیار شما قرار می دهد.شروع به کاردر ابتدا Cobra Generator را نصب کنید.$ go get github.com/spf13/cobra/cobraبعد از اتمام نصب با دستورات زیر پروژه جدیدی ایجاد کنید.$ mkdir myApp; cd myApp
$ cobra init --pkg-name myAppلیست فایل های ایجاد شدهاگر ورژن گو شما ۱.۱۱ یا بالاتر باشد می توانید از Go Module برای مدیریت کتابخانه های مورد استفاده در برنامه خود، استفاده نمایید. $ go mod init myAppدو فایل go.mod و go.sum ایجاد خواهد شد، سپس کبرا را نصب کنید.$ go get -u github.com/spf13/cobraشاید سئوال برایتان پیش بیاید که تفاوت دو نسخه که نصب کردیم چه می باشد؟ اولین پکیج که نصب شد در واقع یک جنریتر می باشد و یک ساختار اولیه برای برنامه ایجاد میکند. نصب مورد اولی کاملا اختیاری می باشد و فقط برای راحتی استفاده می شود.ایجاد یک دستوربرای ایجاد یک دستور در برنامه خود دستور زیاد را اجرا کنید.$ cobra add datetimeبجای datetime نام دستور مورد نظر را وارد کنید.حال اگر فایل cmd/datetime.go را باز کنید باید تقریبا مطابق تصویر زیر باشد.datetime.goقسمت اول زیر بخش import ها محل تعریف دستور می باشد. همانطور که مشاهده می کنید متغیر datetimeCmd یک struct از نوع Command می باشد که فیلد های آن به شرح زیر می باشند.Use: با استفاده از آن می توانید دستور را فراخوانی کنیدShort: یک توضیح مختصر در مورد دستور می باشدLong: توضیح مفصل در مورد دستور می باشدRun: عملیاتی که موقع فراخوانی اجرا می شود داخل این بخش قرار می گیردتابع init در پایینترین قسمت فایل در واقع وظیفه متصل کردن این دستور به ساختار برنامه را دارد.خب حالا برای تست برنامه مراحل زیر را طی کنید.$ go install myApp 
// فایل باینری را به مسیر گو اضافه می کند تا برای کامپیوتر قابل شناسایی باشد
$ myApp -hخروجی نهاییتصویر بالا نشان دهنده راهنمای برنامه می باشد، قسمت اول توضیح مفصل دستور root برنامه می باشد ( cmd/root.go )، بخش Usage نوع استفاده از برنامه را نمایش می دهد و Available Commands دستورات موجود در برنامه را لیست می کند که دستوری datetime هم پیداست. اگر با خط فرمان لینوکس/ویندوز/مک آشنا باشید با مفاهیم این تصویر مخصوصا Flags آشنا خواهید بود اگر نه در ادامه شرح داده خواهد شد.خب، با کلیت فایل آشنا شدیم، حالا می خواهیم وقتی کاربر دستور زیر را اجرا کرد، تاریخ و زمان حال را چاپ کنیم.$ myApp datetimeبرای این کار کافی است خطوط زیر را داخل تابع مقابل Run قرار دهید.dateTime := time.Now()
fmt.Println(dateTime)آشنایی با Flags هافلگ ها در واقع کنترل کننده های دستور هستند که به کاربر اجازه می دهند تا نوع اجرا، اطلاعات اولیه، نوع خروجی و ... یک دستور را مشخص کنند. Flags alter the default behavior of commandsبرای ایجاد یک فلگ برای دستور datetime کافی است خط زیر را در انتهای تابع init اضافه کنید.datetimeCmd.Flags().StringP(&amp;quotformat&amp;quot, &amp;quotf&amp;quot, &amp;quot&amp;quot, &amp;quotFormat for datetime&amp;quot)
// args:
// 0: Full Name
// 1: Shorthand 
// 2: Default Value
// 3: Descriptionو برای استفاده از آن داخل تابع  Runformat, err := cmd.Flags().GetString(&amp;quotformat&amp;quot)
if err != nil {
    log.Fatalln(err)
}
dateTime := time.Now()
if format == &amp;quot&amp;quot {
    fmt.Println(dateTime)
} else {
   fmt.Println(dateTime.Format(format))
}یادتان نرود &quot;log&quot; را import کنید.در نهایت:فایل نهاییخب حالا ببینیم چی داریم!$ go install myApp
$ myApp  datetime -f &amp;quot2006/01/02-15:04:05&amp;quot
// Or 
myApp  datetime --format &amp;quot2006/01/02-15:04:05&amp;quotدر مورد فرمت تاریخ و زمان اینجا بخوانید.خروجی ها با فلگ و بدون فلگتوضیحات پایانیدر این بلاگ پست سعی شده است به صورت مختصر آشنایی اولیه با Cobra ایجاد شود، قطعا این کتابخانه قابلیت های شخصی سازی متنوع تری دارد که بیان آن ها در این پست گنجایش ندارد، در صورت علاقه مندی می توانید به داکیومنت مراجعه کنید. لطفا نظرات و انتقادات خودتونو برای بهتر شدن این نوشته مطرح کنید.برای مشاهده نمونه کاملتر اینجا مراجعه کنید. ( برنامه خط فرمان برای تولید نمودار بر اساس دیتای ورودی )در انتها از وقتی که گذاشتید تشکر میکنم.GitHubLinkedIn</description>
                <category>امیر اسمعیلی</category>
                <author>امیر اسمعیلی</author>
                <pubDate>Mon, 28 Sep 2020 20:34:50 +0330</pubDate>
            </item>
                    <item>
                <title>SSR ( Server-Side Rendering ) و پیاده سازی آن در انگولار</title>
                <link>https://virgool.io/@amiresm17/ssr-server-side-rendering-%D9%88-%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-%D8%A2%D9%86-%D8%AF%D8%B1-%D8%A7%D9%86%DA%AF%D9%88%D9%84%D8%A7%D8%B1-itvlovxrnyum</link>
                <description>Angular Universalتا حدود چند ماه پیش تنها کاری که سمت فرانت انجام داده بودم، چند خط html/css خیلی ناجور و دست و پا شکسته بود. تا این که سر یک پروژه ای به هر دلیلی نتونستیم کسی رو پیدا کنیم که بالاخره خودم دست به کار شدم و یکم انگولار یاد گرفتم و بقیه چیز هارو هم کم کم آماده کردم. در مورد انگولار مطالب زیادی تو اینترنت به زبان انگلیسی و فارسی هست ولی در مورد ssr که تکنیک نسبتا مهمی توی سرعت بارگزاری سایت و حتی SEO هست خیلی کم و ناقص بود، پس تصمیم گرفتم خرده چیز هایی که میدونم و فهمیدم رو به اشتراک بذارم.اس اس آر ( SSR ) چیست ؟امروزه که فریمورک های برنامه نویسی سمت کاربر روز به روز در حال گسترش می باشد، عمده شرکت ها و برنامه نویس ها هم برای بهینه کردن اپلیکیشن و هم بخاطر به صرفه بودن زمان به سمت فریمورک ها روی می آورند. این فریمورک ها ابزار های قدرتمندی رو به برنامه نویس ارايه میدن که این قدرتشون بخاطر JavaScript یا TypeScript ( انگولار ) هستش.توی این فریمورک ها برنامه نویس شاید اصلا بیشتر از ده بیست خط کد js ننویسه و بیشتر کار هاشو با همون html/css انجام بده ولی !!!! اگه داخل مرورگرتون جاوا اسکریپت غیرفعال باشه، شما بدون شک جز یک صفحه سفید خالی چیز دیگه ای نخواهید دید!.شاید بپرسید کی توی سال 2020 ( سالی که دارم می نویسم ) جاوا اسکریپت نداره؟ سوأل خیلی خوب و به جایی هستش. تقریبا همه گوشی ها سخت افزار های چندین سال اخیر جاوا اسکریپت دارن ولی بحث سر چیز دیگه ای هست. ربات ها یا Crawler ها. در واقع در حالت معمولی وقتی یک سایت لود میشه یه متن Loading ... روی صفحه ( توی انگولار اینطوریه ) نمایش داده میشه تا کاملا منابع سایت رندر بشه و وقتی تکمیل شد شما ظاهری که طراحی کرده بودید رو مشاهده می کنید. ولی بذارید اینجوری بگیم که کراولر هایی مثل گوگل / بینگ / فیسبوک / توییتر حوصله موندن توی سایت تا وقتی که جاوا اسکریپت رندر بشه رو ندارن و همون لحظه که سایت باز میشه و فرضا loading مشاهده میکنن در زمان خیلی پایین همون متن ساده رو میبینن و خارج میشن. حالا فرض کنیم شما یک ظاهر خیلی عالی طراحی کردی یک نفر محتوا کار هم داری ولی موتور های جستجو سایت رو index نمیکنن پس کسی هم نمیبینتت پس ...خب چیکار کنیم ؟یکی از تکنیک ها استفاده از ssr می باشد. توی این تکنیک سایت سمت سرور کاملا رندر میشه و فایل های رندر شده رو به سمت مرورگر میفرسته. تو این حالت در همون لحظه که سایت باز میشه کاربر یا کراولر ها میتونن یک صفحه استاتیک از عنصر های html/css مشاهده کنن که باعث میشه گوگل و موتور های جستجوی دیگه بتونن محتوای سایت رو ببینن و توی لینک های داخل سایت اصطلاحا بخزن که اینجا وارد بحث SEO میشه که باعث میشه سایت شما توی نتایج گوگل / بینگ / ... بالاتر بیاد.چجوری پیاده سازی کنیم ( انگولار 6+)تا همین چند وقت پیش برای این کار شما باید تمام فایل هارو دستی ایجاد می کردی ولی به لطف add schematic انگولار این کار خیلی راحت ( در حد آب خوردن عرض میکنم ) شده.اول از همه مطمئن بشید انگولار رو روی سیستمتون دارید.$ npm install [-g] @angular/cliخب حالا یه پروژه جدید ایجاد می کنیم.$ ng new {project_name}ایجاد پروژه جدیدتو این قسمت از شما سئوال می پرسه که آیا میخواید یه ماژول دیگه برای مدیریت روت ( Route ) ها ایجاد بشه. توصیه میکنم قبول کنید. ( D: ). در مرحله بعدی نوع فایل style رو انتخاب کنید و صبر کنید تا نصب تموم بشه. خب اگه پیغام ✔ Packages installed successfully رو دیدین حله.حالا یک آدرس جدید ایجاد میکنیم.دستور های زیر رو وارد کنید.$ cd {project_name}$ ng g m about  --route about --module appتوضیحات مختصری در مورد سطر دوم بدم : g : generate m: moduleتوی این دستوری یک ماژول و کامپوننت جدید به اسم about با آدرس about ایجاد میشه.شما میتونستید فقط یک کامپوننت ایجاد کنید که کفایت می کرد ولی خواستم با روش Lazy Loading هم آشنا بشید. ( توی این روش وقتی سایت بالا میاد تمامی کامپوننت ها لود نمیشن بلکه با رفتن به آدرس هر ماژول کامپوننت هاش بارگزاری میشن که سرعت اپلیکیشن رو بالا می بره.محتوای app.component.html رو بصورت زیر تغییر بدید.&lt;h1&gt;Test SSR&lt;/h1&gt;
&lt;a routerLink=&amp;quot/&amp;quot&gt;Home&lt;/a&gt;
&lt;br&gt;
&lt;a routerLink=&amp;quot/about&amp;quot&gt;About&lt;/a&gt;
&lt;router-outlet&gt;&lt;/router-outlet&gt;حالا با دستور زیاد اپلیکیشن رو اجرا کنید.$ ng serveصفحه ایجاد شدهصفحه ای که باید ببینید این شکلیه. حالا لطفا راست کلیک کنید و روی گزینه View page source کلیک کنید.page sourceبه تگ های &lt;app-root&gt; توجه کنید. اونجا جایی هست که تمام چیزایی که درست کردیم باید نشون داده بشه مثل همون لینک های about و home که در صفحه اول قرار دادیم. این همون جاوا اسکریپت هست که در اول مطلب بهش اشاره کردم. همونطوری که گفتم وقتی کراولر وارد سایت میشه هیچ کدوم از لینک ها و محتویات ما رو نمیبینه. ( اگه میخواین مطمئن باشید جاوا اسکریپت مرورگرتون رو خاموش بکنید. )با دستور زیر فریمورک Universal رو به پروژه تون اضافه کنید.$ ng add @nguniversal/express-engine --clientProject {project_name}خب اگه پیغام ✔ Packages installed successfully رو دیدین حله.خب وقتش رسیده نتیجه کار رو ببینیم. دستور زیر رو بزنید.$ npm run build:ssr &amp;&amp; npm run serve:ssrتوجه داشته باشید که برای مشاهده سایت بصورت ssr باید دستور بالا اجرا بشه و با ng serve به حالت Client-Side Rendering بر میگردیم.وقتی که بیلد و اجرا تموم شد، داخل مرورگرتون به آدرس localhost:4000 برید و سایت رو مشاهده کنید. حالا اگر هم جاوا اسکریپت رو غیر فعال کنید باز هم میتونید بین لینک ها حرکت کنید و محتوای سایت رو مشاهده کنید. توی این روش درواقع سرور شما محتویات سایت شما رو رندر میکنه و کل source سایت رو به سمت کاربر میفرسته و مرورگر دیگه موظف نیست فایل ها رو رندر کنه. حالا View page source رو دوباره بزنید.SSRهمونطوری که مشاهده میکنید داخل تگ app-root المنت های html قابل مشاهده هستش و این صفحات مثل صفحات خالص html باهاشون برخورد میشه و این امکان رو میده که هم صفحه سریعتر لود بشه و هم توسط کراولر ها شناسایی بشیم.آمار نشون میده که کاربر سایتی رو که صفحه اولش بیشتر از 3000ms طول میکشه لود شدنش،‌ با احتمال بیشتری در همون لحظات اول ترک میکنه.معایب این تکنیکاین تکنیک مثل همه چیز معایب خودشو داره که بهتره بیان بشه.چون توی این کار همه فرایند رندر سمت سرور انجام میشه امکان داره بار سنگینی به دوش سرور بیوفته و اگه سرورتون به حد تعداد درخواست ها قوی نباشه به مشکل بربخوره.در این روش باید از شئ های مربوط به مرورگر مثل window, location, DOM خیلی محتاطانه استفاده بکنید. چون سرور هیچ کدوم از این هارو نمیشناسه. راه حل : سعی کنید اصطلاحا انگولاری برید جلو یعنی در حد امکان از این شئ ها استفاده نکنید ولی اگر مجبور شدید یا مثلا افزونه ای نصب کردید که به این شئ ها نیاز داشت ( مثل نقشه گوگل مپ ) اونموقع از تابع isPlatformBrowser که داخل پکیج angular/common قرار داره استفاده کنید و مشخص کنید که اگه داخل مرورگر بودیم به این شئ ها دسترسی پیدا کنه.توصیه میکنم روش های دیگه که برای حل این مشکل وجود داره مانند prerender رو هم مطالعه کنید و همچنین شرکت هایی مثل prerender.io با قیمت کم این کار رو برای شما انجام میدن.منابعAngular DocumentNg Talksامیدوارم این مطلب به دردتون بخوره. :)منو دنبال کنید.TwitterGitHubLinkedIn</description>
                <category>امیر اسمعیلی</category>
                <author>امیر اسمعیلی</author>
                <pubDate>Mon, 30 Mar 2020 02:44:28 +0430</pubDate>
            </item>
                    <item>
                <title>دیتا ساینس، اینبار خوشگلتر!</title>
                <link>https://virgool.io/hooshteam/streamlit-go9s7kwenjh8</link>
                <description>Streamlitتوی این چند سال اخیر گرایش دانشجوهای کامپیوتر به سمت علم داده بیشتر شده و هر روز پیشرفت های چشم گیری تو این حوزه اتفاق میوفته. توی علم داده یکی از قسمت های مهم روش نشون دادن داده هاست. شاید شما بتونید به بهترین شکل داده هاتون رو جمع آوری کنید و تحلیل کنید؛ ولی اگر نتونید اون هارو به صورت بصری نشون کارفرما بدید قطعا با مشکل جدی مواجه خواهید شد.Streamlitاسم کتابخونه ای هست که بر روی پایتون قابل استفاده است، که باهاش میتونید در قالب یک وب اپلیکیشن داده هارو بصورت نمودار، جدول و ... نشون بدید. قسمت خیلی باحال این کتابخونه اینه که بصورت real-time به شما پاسخ میده؛ یعنی با هر تغییر در پارامتر ها نمودارها و جدول ها آپدیت میشن.توی این پست قصد دارم بصورت خیلی جزیٔی این کتابخونه رو معرفی کنم.کد و داده های اولیه اینجا هستن!نصب و راه اندازیاولش streamlit رو با pip ورژن دلخواهتون نصب کنید.pip install streamlitحالا یک فایل با فرمت py ایجاد کنید و داخل فایل سطر های زیر رو اضافه کنید و در آخر ذخیره کنید.import streamlit as st

st.write(&#039;Hello World&#039;)حالا وارد ترمینال دستگاهتون بشید و دستور زیر رو وارد کنید.$ streamlit run hello_world.pyصفحه مرورگر پیشفرضتون باز میشه و یک صفحه با عبارت Hello World مشاهده می کنید.پیاده سازی یک وب اپلیکیشن سادهخب کتابخونه نصب شد و می تونیم با داده های واقعی تر کار کنیم. تو این آموزش من از یک فایل csv که حاوی اطلاعات 1000 فیلم محبوب از نظر IMDB و کتابخونه pandas استفاده می کنم. قراره یک اپلیکیشینی درست کنیم که با توجه به پارامتر هایی که کاربر میده ( تعداد سطر و ستون های انتخابی )، فایل csv رو نمایش بدیم و در انتها نمودار توزیع پراکندگی امتیازات این داده هارو رسم کنیم.یک فایل پایتون به اسم imdb-data-visualize.py ایجاد میکنم.مثل قسمت قبل باید streamlit رو وارد کنید.import streamlit as st
import pandas as pdحالا عنوان برنامه رو مشخص کنید.st.title(&#039;1000 Popular Movies&#039;)هربار که فایل رو سیو کنید و مرورگرتون رو رفرش کنید تغییرات رو مشاهده می کنید.صفحه اول بعد از آپدیت عنوانلازمه که داده های اولیه رو وارد کنیم.data = pd.csv_read(&#039;&#039;./IMDB-Movie-Data.csv&amp;quot,  index_col=&amp;quotTitle&amp;quot)استریم لیت ویجت هایی داره که با استفاده از اونها می تونید اکثر المنت های یک وبسایت رو با یک خط کد بالا بیارید.ویجت اسلایدر :با استفاده از این ابزار می تونید به کاربر اجازه بدید که یک عدد رو توی یک بازه مشخصه انتخاب کنه.num_of_rows = st.sidebar.slider(&amp;quotSelect number of rows you wish to load data&amp;quot, min_value=1, max_value=data.shape[0], value=20)اگه به کد توجه کنید قسمت sidebar رو مشاهده می کنید. این خط رو وارد کنید و مرورگرتون رو رفرش کنید. یک ویجت اسلایدر میبینید که در سمت چپ صفحه داخل یک پنل قرار داره. حالا اینبار sidebar رو حذف کنید یعنی این خط بصورت زیر باشه : num_of_rows = st.slider(&amp;quotSelect number of rows you wish to load data&amp;quot, min_value=1, max_value=data.shape[0], value=20)تو این حالت ویجت مورد نظر داخل صفحه اصلی قرار میگیره. ما با کد اول ادامه میدیم ولی اگه شما دوست دارید میتونید هرجا که خواستید sidebar رو حذف کنید.ویجت انتخاب چندگانه (multiselect) :با این ویجت می تونید به کاربر امکان انتخاب یک یا چند مورد مشخص رو بدید.columns = st.sidebar.multiselect(&#039;Select desired columns(empty for all)&#039;, data.columns)این عنصر رو هم مثل عنصر قبلی داخل sidebar قرار میدیم. پارامتر اول متنی هست که نمایش داده میشه و پارامتر دوم موارد قابل انتخاب ( بصورت یک لیست یا آرایه numpy ) است. پانداز ( pandas ) فایل csv شما رو بصورت یک دیتافریم میخونه و ویژگی columns ستون های دیتاست شما رو بصورت یک لیست بر میگردونه.حالا یک چکباس وارد می کنیم برای اینکه کاربر اگه بخواد تو صفحه اصلیش جدول رو با پارامتر هایی که خودش انتخاب کرده مشاهده کنه.if st.sidebar.checkbox(&amp;quotView the table&amp;quot):
    if len(columns)==0:   
        st.write(data.head(num_of_rows))
    else:
        st.write(data.head(num_of_rows)[columns])ویجت چکباکس اگه انتخاب بشه مقدارTrue برمیگردونه و در غیر اینصورت False. در سطر بعدی مشخص میشه اگر کاربر هیچکدوم از ستون هارو انتخاب نکرده باشه ( لیستی که multiselect برگردونده بود خالی باشه ) streamlit به تعداد num_of_value از داده هاشو نشون بده در غیر اینصورت فقط ستون های انتخاب شده کاربر رو نشون بده.خب؛ برای اینکه نشون بدیم توی این کتابخونه چطوری با نمودار ها کار کنیم. میخوایم هیستوگرام توزیع امتیازات فیلم هارو بر اساس تعداد داده های انتخابی کاربر نمایش بدیم.پانداز ( pandas ) خودش از کتابخونه matplotlib برای رسم نمودار ها استفاده میکنه.if st.sidebar.checkbox(&#039;View rating histogram&#039;):
    st.write(&#039;## Ratings&#039;)
    data[[&#039;Rating&#039;]].head(num_of_rows).plot(kind=&#039;hist&#039;)
    st.pyplot()تو این قسمت دوباره از یه چکباکس استفاده کردم که با انتخابش نمودار توزیع امتیازات فیلم هارو نشون میده.حالا فایل رو ذخیره و مرورگرتون رو رفرش کنید تا نتیجه کار رو ببینید.خروجی نهاییخب، این فقط یه بخش کوچیک از streamlit بود. امیدوارم که علاقه مند بشید و بیشتر ازش استفاده بکنید.:)</description>
                <category>امیر اسمعیلی</category>
                <author>امیر اسمعیلی</author>
                <pubDate>Sat, 19 Oct 2019 21:00:23 +0330</pubDate>
            </item>
            </channel>
</rss>