@Jut_Rut

Как заставить процесс запустить определённую процедуру?

Я пытаюсь сделать подбор пароля к архиву. Сам подбор работал на малых паролях, но я решил попробовать 5-ти символьный, где есть 147 знаков и понял, что не доживу, пока он взломается.

Я захотел сделать более быстрый код, в пайтоне, насколько я понял, это делается процессами. Я передаю процессору процедуру, которую он должен был бы сделать, но почему-то вижу странный вывод, будто main дублирует команды, которые были до этого. Подскажите, что тут происходит и как это можно решить, пожалуйста.

Сама логика такова: в цикле генерируются пароли, когда их batch_gen_len, они переходят в функцию, которая разбивает их на количество пакетов batch_count, в каждом пакете по one_batch_len. Затем вся эта структура передаётся в try_Proc, где пакеты по one_batch_len должны распределяться между batch_count процессами. Запускаю код, а меня ждёт очень странный вывод структуры пакета, который по логике на том участке кода уже не генерируется. Main будто в странном режиме запускается заново и я никак не могу объяснить почему.

65e5e0ff85e46420355981.png

from itertools import product
from datetime import datetime
from pyzipper import AESZipFile
from multiprocessing import *
from time import sleep


k = 0
el = [1, 2, 3]

syms = '0123456789"№;%:?*()_+-=&^$3#@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZабвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ'
pass_len = 3
path = 'test.zip'
max_len = len(syms)**pass_len
batch_gen_len = 10
batch_count = 5
one_batch_len = int(batch_gen_len/batch_count)

assert not one_batch_len > int(one_batch_len), "не дробное число"

passwd = None
end = False
main_lst = []

start = datetime.now()
print(start)
k = 0
z = AESZipFile(path, encryption='utf-8')


def show_progress():
    if(k % 100000 == 0):
        print(str(k / max_len * 100) + '%')


def try_Lst(lst: list):
    for p in lst:
        try_pass(p)


def try_Proc(batches):
    all_proc = []
    for batch in batches:
        proc = Process(target=try_Lst, args=(batch,))
        all_proc.append(proc)
    if __name__ == "__main__":
        for proc in all_proc:
            proc.start()
        for proc in all_proc:
            proc.join()
    sleep(10)


def try_pass(p):
    global k, z, passwd, end
    print(p)
    show_progress()
    k += 1
    try:
        z.extractall(pwd=bytes(p, 'utf-8'))
        end = True
        passwd = p
    except:
        pass


def gen_batches():
    global main_lst
    batches = []
    f = 0
    s = one_batch_len
    for i in range(batch_count):
        batches.append(main_lst[f:s])
        f += one_batch_len
        s += one_batch_len

    print(batches)
    return batches


for p in product(syms, repeat=pass_len):
    main_lst.append(''.join(p))
    if end: break
    if len(main_lst) == batch_gen_len:
        batches = gen_batches()
        main_lst.clear()
        try_Proc(batches)


z.close()
end = datetime.now()
print(k)
print(end)
print(end-start)
  • Вопрос задан
  • 53 просмотра
Решения вопроса 1
Vindicar
@Vindicar
RTFM!
Если на пальцах:
1. В питоне всё - оператор. Вот вообще всё, кроме комментариев. Объявление функции - такой же оператор, как и цикл.
2. Как следствие, нет формального понятия "тело программы". Ты должен сам указать, что является телом, завернув его в if __name__ == '__main__:
3. Чтобы выполнить подпрограмму, дочерний процесс должен выполнить код, который её определит. А единственный способ это сделать - выполнять файл с самого начала.
4. Если ты не указал тело программы - дочерний процесс выполнит всё, в том числе запуск дочернего процесса. Что обычно не требуется.
Так что правильно выглядящая программа с мультипроцессингом должна иметь только такой вид:
def func1():
    ...

def func2():
    ...

...
if __name__ == '__main__':
    ... # тут запуск дочерних процессов


А ещё данные передаются между процессами с помощью модуля pickle, так что твои распаралленные функции могут принимать и возвращать только такие объекты, которые можно упаковать с помощью pickle.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы