وبلاگ فربد | Farbod Blog

توی این وبلاگ راجع به پروژه هام صحبت می کنم

آموزش پردازش موازی در پایتون

  • ۱۳۶۹

سلام دوستان :)

 

توی دو تا پست قبلی من نحوه ساخت کرکر های فایل های zip و rar رو به اشتراک گذاشتم. توی این پست هم میخوایم این دو تا کرکر رو با هم بهینه و پر سرعت کنیم و ببینیم که multiprocessing به چه معناست و چه کاربردی داره. پس قبل از خوندن این پست حتما بهتون پیشنهاد میکنم پست (ساخت کرکر فایل های zip) و پست (کرک فایل های winrar) رو بخونید و بعد بیاید ادامه پست...

 

اول از همه باید یک سری مفاهیم رو بهتون توضیح بدم.

 

1- Program : فایل های اجرایی هستن که روی هارد ذخیره میشن و قابل اجرا هستن.
 
2- Process: موقعی که یک برنامه روی کامپیوتر اجرا بشه یک قسمت از حافظه رو به خودش اختصاص میده و تبدیل به یک Process لایو توی سیستم میشه.
 
3- Thread: یک بخش کوچک از Process است. هر Process از چندین Thread تشکیل میشه.
 

 

با توجه به توضیحاتی که بالا دادم فرض کنید که ما یک اسکریپت کرکر نوشتیم. برنامه ما اجرا میشه و یک Process زنده توی سیستم عامل ما تشکیل میده و هر یک از توابعی که توی برنامه مون نوشتیم تبدیل به یک Thread میشه.

اما زبان برنامه نویسی پایتون طوری طراحی شده که بیشتر از یک Thread نمیتونه روش اجرا بشه.

 

برنامه زیر رو فرض کنید:

def func1():
    print("function1")
def func2():
    print("function2")

func1()
func2()

 

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

اتفاقی که میفته اینه که interpreter پایتون به هیچ عنوان به ما اجازه اجرا کردن دو تا Thread به صورت همزمان رو نمیده بنابراین اول تابع 1 اجرا میشه و بعد هم تابع 2، یعنی چیزی به اسم اجرای همزمان وجود نداره ! به این GIL (مخفف Global Interpreter Lock) میگن.

 

خوشبختانه ماژول ها و کتابخونه هایی برای انجام دادن این کار موجودن.

کتابخونه ‌threading برای انجام multithreading و کتابخونه multiproccessing برای multiprocessing. اما هر کدوم از اینها به چه معنا هستند؟

 

1- multiprocessing :
توی multiproccessing ما میایم با استفاده از یک سری روش ها، چندین proccess روی سیستم عامل ایجاد میکنیم تا بتونیم از تمام هسته های cpu استفاده کنیم. توی این روش تبادل اطلاعات بین Process ها یکم سخته.
2- multithreading :
توی  multithreading ما میایم چندین thread رو با هم اجرا میکنیم. توی این روش تبادل اطلاعات بین thread ها خیلی آسونه، چون تمام thread ها توی یک Process قرار دارن.

 

توی این پست ما از روش multiprocessing استفاده خواهیم کرد.

 

اگر بخوایم دو تا تابع داخل برنامه بالا رو همزمان اجرا کنیم باید به صورت زیر عمل کنیم:

import multiprocessing as m

def func1():
    print("function1")
def func2():
    print("function2")

p1 = m.Process(target=func1)
p2 = m.Process(target=func2)

p1.start()
p2.start()

توضیح: اول ماژول multiproccessing رو با نام m توی برنامه مون import کردیم. بعدش دوتا تابع به نام func1 و func2 تعریف کردیم. بعدش از کلاس Process استفاده کردیم و ورودی target رو برابر func1 قرار دادیم. داخل ورودی target باید تابعی که میخوایم ازش یک Proccess ایجاد کنیم رو قرار بدیم. خط بعد هم یک Process از تابع دوممون ساختیم.

توی دو خط بعدی هم با استفاده از متد Process ,start هامون رو اجرا کردیم.

اتفاقی که توی این برنامه میفته اینه که اول یک Process از func1 ایجاد میشه و بعد یک Process از func2 و دو تاشون با هم توی دو تا Process مستقل اجرا میشن و این هم همونیه که ما میخوایم ! استفاده از تمام هسته های cpu !

 

خب پس بریم سراغ اون دو تا اسکریپت که قراره با هم پر سرعتشون کنیم.

اگه یادتون باشه اسکریپت کرک فایل های zip به این صورت بود:

from zipfile import ZipFile
from datetime import datetime

zf = input("Zip File : ")
passlist = input("Password List : ")

zf = ZipFile(zf)
tests = 0
start_time = datetime.now()
for password in open(passlist):
    password = password.strip("\n")
    print("Testing : {}".format(password))
    tests += 1
    try:
        zf.extractall(pwd=password.encode())
        end_time = datetime.now()
        t = end_time - start_time
        print("-"*50)
        print("Password : {}     ||     {} Passwords Tested in {} seconds !".format(password,tests,t.total_seconds()))
        input()
        break
    except :
        continue

و اسکریپت کرک فایل های rar هم به این شکل بود:

import rarfile
import sys

rarfile_address = input("RarFile : ")
passwordlist_address = input("Password List : ")

rar_file = rarfile.RarFile(rarfile_address)

passwordlist = open(passwordlist_address)

password_found = False
print("-----------------")
for password in passwordlist:
    password = password.strip("\n")
    print("Testing : {}".format(password))
    try:
        rar_file.setpassword(password)
        rar_file.testrar()
        print("*"*50)
        print("Password : {}".format(password))
        password_found = True
        break
    except rarfile.RarWrongPassword:
        continue

if password_found:
    input()
    sys.exit(0)
else:
    print("*"*50)
    print("Sorry I can't find correct Password in your password list :(")

 

خب حالا بریم سراغ بهینه کردن اسکریپت ها.

سورس تغییر یافته کرک فایل های zip:

from zipfile import ZipFile
from datetime import datetime
import multiprocessing as m # new
import sys

zf = input("Zip File : ")
passlist = input("Password List : ")

def testpassword(password): # new
    try:
        zf.extractall(pwd=password.encode())
        end_time = datetime.now()
        print("-"*50)
        print(f"Password : {password}.found in : {end_time-start_time} seconds !")
        input()
        sys.exit(0)
    except :
        continue

zf = ZipFile(zf)
tests = 0
start_time = datetime.now()
for password in open(passlist):
    while len(m.active_children()) > 16 : #‌ new
        continue
    password = password.strip("\n")
    print("Testing : {}".format(password))
    p = m.Process(target = testpassword, args = (password, )) # new
    p.start() # new

قسمت های جدید با new# مشخص شدن

توضیح: اولین تغییری که دادیم اینه که بخش تست کردن پسورد ها رو بردیم توی یک تابع به نام testpassword و یک ورودی password براش مشخص کردیم. دومین تغییر توی حلقه for هستش، اگر دقت کنید پایین برنامه یک حلقه for میبینید داخل اون یک while اضافه کردیم که میگه تا وقتی تعداد process ها 16 تا بودن ادامه بده بعنی حداکثر 16 تا password رو با هم امتحان کنه. مقدار این عدد بستگی به قدرت سیستم خودتون داره.

سومین تغییر اینه که داخل همون for گفتیم که یک Process از تابع testpassword بساز و توی ورودی args بهش یک Tuple دادیم که توی Tuple باید مقادیری که میخوایم به تابع ما داده بشه رو مشخص کنیم (کاما رو برای این گذاشتیم که مقداری که دادیم تبدیل به یک Tuple بشه). در خط بعدی هم با استفاده از متد start پروسس خودمون رو اجرا کردیم.

 

خب این از سورس تغییر یافته کرک فایل های zip.

بریم سراغ سورس تغییر یافته کرک فایل های rar.

 

سورس تغییر یافته کرک فایل های rar:

import rarfile
import time
import multiprocessing as m # new
import sys

def testpassword(password): # new
    try:
        rar_file.setpassword(password)
        rar_file.testrar()
        end = time.time()
        print("*"*50)
        print(f"Password : {password} . find in {end-start} seconds")
	    input()
        sys.exit(0)
    except:
        pass

rarfile_address = input("RarFile : ")
passwordlist_address = input("Password List : ")

rar_file = rarfile.RarFile(rarfile_address)

passwordlist = open(passwordlist_address)

start = time.time()
for password in passwordlist:     
    while len(m.active_children()) > 16 : #‌ new
        continue
    password = password.strip("\n")
    p = m.Process(target = testpassword, args= (password,)) # new
    p.start() # new

قسمت های جدید با new# مشخص شدن

این سورس هم با بالایی فرقی نداره و قسمت هایی هم که فرق داره توی پست (کرک فایل های winrar در پایتون) توضیح دادم.

 

امیدوارم براتون مفید بوده باشه D:


ارسال نظر آزاد است، اما اگر قبلا در بیان ثبت نام کرده اید می توانید ابتدا وارد شوید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">
تجدید کد امنیتی