Как исправить ошибку «TypeError: невозможно сериализовать объект« _io.BufferedReader »при попытке многопроцессорной обработки - PullRequest
0 голосов
/ 03 февраля 2019

Я пытаюсь переключить многопоточность в своем коде на многопроцессорность, чтобы измерить его производительность и, надеюсь, достичь более высокого потенциала для перебора, поскольку моя программа предназначена для защиты от перебора файлов .zip.Но всякий раз, когда я пытаюсь запустить программу, я получаю следующее:

BruteZIP2.py -z "Generic ZIP.zip" -f  Worm.txt
Traceback (most recent call last):
  File "C:\Users\User\Documents\Jetbrains\PyCharm\BruteZIP\BruteZIP2.py", line 40, in <module>
    main(args.zip, args.file)
  File "C:\Users\User\Documents\Jetbrains\PyCharm\BruteZIP\BruteZIP2.py", line 34, in main
    p.start()
  File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\multiprocessing\process.py", line 112, in start
self._popen = self._Popen(self)
  File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\multiprocessing\context.py", line 223, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
  File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\multiprocessing\context.py", line 322, in _Popen
return Popen(process_obj)
  File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\multiprocessing\popen_spawn_win32.py", line 65, in __init__
reduction.dump(process_obj, to_child)
  File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\multiprocessing\reduction.py", line 60, in dump
ForkingPickler(file, protocol).dump(obj)
TypeError: cannot serialize '_io.BufferedReader' object

Я обнаружил потоки, у которых была та же проблема, что и у меня, но они оба остались без ответа / не решены.Я также попытался вставить Pool выше p.start(), так как считаю, что это было вызвано тем, что я на компьютере с Windows, но это не помогло.Мой код выглядит следующим образом:

  import argparse
  from multiprocessing import Process
  import zipfile

  parser = argparse.ArgumentParser(description="Unzips a password protected .zip by performing a brute-force attack using either a word list, password list or a dictionary.", usage="BruteZIP.py -z zip.zip -f file.txt")
  # Creates -z arg
  parser.add_argument("-z", "--zip", metavar="", required=True, help="Location and the name of the .zip file.")
  # Creates -f arg
  parser.add_argument("-f", "--file", metavar="", required=True, help="Location and the name of the word list/password list/dictionary.")
  args = parser.parse_args()


  def extract_zip(zip_file, password):
      try:
          zip_file.extractall(pwd=password)
          print(f"[+] Password for the .zip: {password.decode('utf-8')} \n")
      except:
          # If a password fails, it moves to the next password without notifying the user. If all passwords fail, it will print nothing in the command prompt.
          print(f"Incorrect password: {password.decode('utf-8')}")
          # pass


  def main(zip, file):
      if (zip == None) | (file == None):
          # If the args are not used, it displays how to use them to the user.
          print(parser.usage)
          exit(0)
      zip_file = zipfile.ZipFile(zip)
      # Opens the word list/password list/dictionary in "read binary" mode.
      txt_file = open(file, "rb")
      for line in txt_file:
          password = line.strip()
          p = Process(target=extract_zip, args=(zip_file, password))
          p.start()
          p.join()


  if __name__ == '__main__':
      # BruteZIP.py -z zip.zip -f file.txt.
      main(args.zip, args.file)

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

Моя главная цель здесь - запустить 8 процессов / пулов, чтобы максимизировать количество попыток по сравнению с многопоточностью, но из-за того, что я не могу получить исправление для сообщения TypeError: cannot serialize '_io.BufferedReader' object, я не уверен в том, чтоделать здесь и как я могу это исправить.Любая помощь будет оценена.

1 Ответ

0 голосов
/ 04 февраля 2019

Файловые дескрипторы не очень хорошо сериализуются ... Но вы можете отправить имя файла zip вместо zip filehandle (строка сериализуется нормально между процессами).И избегайте zip для вашего имени файла, поскольку оно является встроенным.Я выбрал zip_filename

p = Process(target=extract_zip, args=(zip_filename, password))

затем:

def extract_zip(zip_filename, password):
      try:
          zip_file = zipfile.ZipFile(zip_filename)
          zip_file.extractall(pwd=password)

Другая проблема заключается в том, что ваш код не будет работать параллельно из-за этого:

      p.start()
      p.join()

p.join ожидает завершения процесса ... вряд ли полезно.В конце вы должны сохранить идентификаторы процесса для join их.

Это может вызвать другие проблемы: создание слишком большого количества параллельных процессов может стать проблемой для вашей машины и после некоторой точки зрения не очень поможет.,Вместо этого рассмотрим multiprocessing.Pool, чтобы ограничить количество работников.

Тривиальный пример:

with multiprocessing.Pool(5) as p:
    print(p.map(f, [1, 2, 3, 4, 5, 6, 7]))

Адаптирован к вашему примеру:

with multiprocessing.Pool(5) as p:
    p.starmap(extract_zip, [(zip_filename,line.strip()) for line in txt_file])

(starmap расширяет кортежи как 2 отдельных аргумента для соответствия вашему extract_zip методу, как описано в Python multiprocessing pool.map для нескольких аргументов )

...