Python3中的多处理
我当时正在摆弄一个zip文件破解程序,并决定使用多处理模块来加速这个过程。因为这是我第一次使用这个模块,我还没有完全理解它,所以这完全是一种痛苦。然而,我让它工作了 问题是它没有完成单词列表;它只是在单词列表中随机停止,如果找到密码,它将继续遍历单词列表,而不是停止进程 有人知道它为什么表现出这种行为吗 ZipFile Cracker的源代码Python3中的多处理,python,multithreading,python-3.x,multiprocessing,cracking,Python,Multithreading,Python 3.x,Multiprocessing,Cracking,我当时正在摆弄一个zip文件破解程序,并决定使用多处理模块来加速这个过程。因为这是我第一次使用这个模块,我还没有完全理解它,所以这完全是一种痛苦。然而,我让它工作了 问题是它没有完成单词列表;它只是在单词列表中随机停止,如果找到密码,它将继续遍历单词列表,而不是停止进程 有人知道它为什么表现出这种行为吗 ZipFile Cracker的源代码 #!/usr/bin/env python3 import multiprocessing as mp import zipfile # Handeli
#!/usr/bin/env python3
import multiprocessing as mp
import zipfile # Handeling the zipfile
import sys # Command line arguments, and quiting application
import time # To calculate runtime
def usage(program_name):
print("Usage: {0} <path to zipfile> <dictionary>".format(program_name))
sys.exit(1)
def cracker(password):
try:
zFile.extractall(pwd=password)
print("[+] Password Found! : {0}".format(password.decode('utf-8')))
pool.close()
except:
pass
def main():
global zFile
global pool
if len(sys.argv) < 3:
usage(sys.argv[0])
zFile = zipfile.ZipFile(sys.argv[1])
print("[*] Started Cracking")
startime = time.time()
pool = mp.Pool()
for i in open(sys.argv[2], 'r', errors='ignore'):
pswd = bytes(i.strip('\n'), 'utf-8')
pool.apply_async(cracker, (pswd,))
print (pswd)
runtime = round(time.time() - startime, 5)
print ("[*] Runtime:", runtime, 'seconds')
sys.exit(0)
if __name__ == "__main__":
main()
#/usr/bin/env蟒蛇3
将多处理作为mp导入
导入zipfile#处理zipfile
导入sys#命令行参数并退出应用程序
导入时间#计算运行时间
def使用(程序名称):
打印(“用法:{0}”。格式(程序名))
系统出口(1)
def破解程序(密码):
尝试:
zFile.extractall(pwd=密码)
打印(“[+]找到密码!:{0}”。格式(Password.decode('utf-8'))
pool.close()
除:
通过
def main():
全局zFile
全球池
如果len(sys.argv)<3:
用法(sys.argv[0])
zFile=zipfile.zipfile(sys.argv[1])
打印(“[*]开始开裂”)
startime=time.time()
pool=mp.pool()
对于打开的i(sys.argv[2],'r',errors='ignore'):
pswd=字节(i.strip('\n'),'utf-8')
pool.apply_async(cracker,(pswd,))
打印(pswd)
runtime=round(time.time()-startime,5)
打印(“[*]运行时:”,运行时,“秒”)
系统出口(0)
如果名称=“\uuuuu main\uuuuuuuu”:
main()
您过早终止程序。要测试这一点,请在cracker
方法中添加无害的time.sleep(10)
,并观察程序在一秒钟内仍将终止
调用以等待池完成:
pool = mp.Pool()
for i in open(sys.argv[2], 'r', errors='ignore'):
pswd = bytes(i.strip('\n'), 'utf-8')
pool.apply_async(cracker, (pswd,))
pool.close() # Indicate that no more data is coming
pool.join() # Wait for pool to finish processing
runtime = round(time.time() - startime, 5)
print ("[*] Runtime:", runtime, 'seconds')
sys.exit(0)
此外,一旦找到正确的密码,调用close
仅表示未来不再有任务出现-所有已提交的任务仍将完成。相反,在不处理任何其他任务的情况下调用以终止池
此外,根据multiprocessing.Pool
的实现细节,全局变量Pool
在需要时可能不可用(其值无论如何都不可序列化)。要解决此问题,可以使用回调,如中所示
def cracker(password):
try:
zFile.extractall(pwd=password)
except RuntimeError:
return
return password
def callback(found):
if found:
pool.terminate()
...
pool.apply_async(cracker, (pswd,), callback=cb)
当然,由于您现在一直在查看结果,apply
不是正确的方法。相反,您可以使用以下方法编写代码:
除了使用globals,您还可能希望在每个进程中通过为池使用一个函数来打开zip文件(并创建一个
ZipFile
对象)。甚至更好(更快),首先放弃所有I/O,只读取一次所需的字节,然后将它们传递给孩子们。phihag的答案是正确的解决方案
我只是想提供一个关于在找到正确密码后调用terminate()
的额外细节。运行代码时,cracker()
中的pool
变量未定义。因此,试图从那里调用它只会引发一个异常:
NameError: name 'pool' is not defined
(我的fork()
经验不足,所以我不完全理解为什么全局zFile
被成功复制到子进程,而pool
却没有。即使它被复制,它在父进程中也不会是相同的pool
,对吗?因此对它调用的任何方法都不会对pare中的真实池产生影响nt进程。无论如何,我更喜欢多处理
模块的编程指南部分中列出的建议:显式地将资源传递给子进程)
我的建议是让cracker()
返回正确的密码,否则返回None
。然后将回调传递给记录正确密码的apply_async()
,并终止池。以下是我对修改代码以实现此目的的看法:
#!/usr/bin/env python3
import multiprocessing as mp
import zipfile # Handeling the zipfile
import sys # Command line arguments, and quiting application
import time # To calculate runtime
import os
def usage(program_name):
print("Usage: {0} <path to zipfile> <dictionary>".format(program_name))
sys.exit(1)
def cracker(zip_file_path, password):
print('[*] Starting new cracker (pid={0}, password="{1}")'.format(os.getpid(), password))
try:
time.sleep(1) # XXX: to simulate the task taking a bit of time
with zipfile.ZipFile(zip_file_path) as zFile:
zFile.extractall(pwd=bytes(password, 'utf-8'))
return password
except:
return None
def main():
if len(sys.argv) < 3:
usage(sys.argv[0])
print('[*] Starting main (pid={0})'.format(os.getpid()))
zip_file_path = sys.argv[1]
password_file_path = sys.argv[2]
startime = time.time()
actual_password = None
with mp.Pool() as pool:
def set_actual_password(password):
nonlocal actual_password
if password:
print('[*] Found password; stopping future tasks')
pool.terminate()
actual_password = password
with open(password_file_path, 'r', errors='ignore') as password_file:
for pswd in password_file:
pswd = pswd.strip('\n')
pool.apply_async(cracker, (zip_file_path, pswd,), callback=set_actual_password)
pool.close()
pool.join()
if actual_password:
print('[*] Cracked password: "{0}"'.format(actual_password))
else:
print('[*] Unable to crack password')
runtime = round(time.time() - startime, 5)
print("[*] Runtime:", runtime, 'seconds')
sys.exit(0)
if __name__ == "__main__":
main()
#/usr/bin/env蟒蛇3
将多处理作为mp导入
导入zipfile#处理zipfile
导入sys#命令行参数并退出应用程序
导入时间#计算运行时间
导入操作系统
def使用(程序名称):
打印(“用法:{0}”。格式(程序名))
系统出口(1)
def破解程序(zip文件路径、密码):
打印('[*]正在启动新的破解程序(pid={0},password=“{1}”)。格式(os.getpid(),password))
尝试:
时间。睡眠(1)#XXX:模拟需要一点时间的任务
zipfile.zipfile(zip文件路径)作为zFile:
zFile.extractall(pwd=bytes(密码“utf-8”))
返回密码
除:
一无所获
def main():
如果len(sys.argv)<3:
用法(sys.argv[0])
打印('[*]启动main(pid={0})'.format(os.getpid())
zip\u file\u path=sys.argv[1]
密码\文件\路径=sys.argv[2]
startime=time.time()
实际密码=无
使用mp.Pool()作为池:
def设置_实际_密码(密码):
非本地实际密码
如果输入密码:
打印(“[*]找到密码;正在停止将来的任务”)
pool.terminate()
实际密码=密码
打开(密码\u文件\u路径'r',errors='ignore')作为密码\u文件:
对于密码_文件中的pswd:
pswd=pswd.strip('\n')
apply\u async(cracker,(zip\u file\u path,pswd,),callback=set\u实际\u密码)
pool.close()
pool.join()
如果实际密码为:
打印(“[*]破解密码:“{0}”。格式(实际密码))
其他:
打印(“[*]无法破解密码”)
runtime=round(time.time()-startime,5)
打印(“[*]运行时:”,运行时,“秒”)
系统出口(0)
如果名称=“\uuuuu main\uuuuuuuu”:
main()
以下是来自和的建议的实施:
#/usr/bin/env蟒蛇3
“”“暴力压缩密码。
用法
#!/usr/bin/env python3
import multiprocessing as mp
import zipfile # Handeling the zipfile
import sys # Command line arguments, and quiting application
import time # To calculate runtime
import os
def usage(program_name):
print("Usage: {0} <path to zipfile> <dictionary>".format(program_name))
sys.exit(1)
def cracker(zip_file_path, password):
print('[*] Starting new cracker (pid={0}, password="{1}")'.format(os.getpid(), password))
try:
time.sleep(1) # XXX: to simulate the task taking a bit of time
with zipfile.ZipFile(zip_file_path) as zFile:
zFile.extractall(pwd=bytes(password, 'utf-8'))
return password
except:
return None
def main():
if len(sys.argv) < 3:
usage(sys.argv[0])
print('[*] Starting main (pid={0})'.format(os.getpid()))
zip_file_path = sys.argv[1]
password_file_path = sys.argv[2]
startime = time.time()
actual_password = None
with mp.Pool() as pool:
def set_actual_password(password):
nonlocal actual_password
if password:
print('[*] Found password; stopping future tasks')
pool.terminate()
actual_password = password
with open(password_file_path, 'r', errors='ignore') as password_file:
for pswd in password_file:
pswd = pswd.strip('\n')
pool.apply_async(cracker, (zip_file_path, pswd,), callback=set_actual_password)
pool.close()
pool.join()
if actual_password:
print('[*] Cracked password: "{0}"'.format(actual_password))
else:
print('[*] Unable to crack password')
runtime = round(time.time() - startime, 5)
print("[*] Runtime:", runtime, 'seconds')
sys.exit(0)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""Brute force zip password.
Usage: brute-force-zip-password <zip archive> <passwords>
"""
import sys
from multiprocessing import Pool
from time import monotonic as timer
from zipfile import ZipFile
def init(archive): # run at the start of a worker process
global zfile
zfile = ZipFile(open(archive, 'rb')) # open file in each process once
def check(password):
assert password
try:
with zfile.open(zfile.infolist()[0], pwd=password):
return password # assume success
except Exception as e:
if e.args[0] != 'Bad password for file':
# assume all other errors happen after the password was accepted
raise RuntimeError(password) from e
def main():
if len(sys.argv) != 3:
sys.exit(__doc__) # print usage
start = timer()
# decode passwords using the preferred locale encoding
with open(sys.argv[2], errors='ignore') as file, \
Pool(initializer=init, initargs=[sys.argv[1]]) as pool: # use all CPUs
# check passwords encoded using utf-8
passwords = (line.rstrip('\n').encode('utf-8') for line in file)
passwords = filter(None, passwords) # filter empty passwords
for password in pool.imap_unordered(check, passwords, chunksize=100):
if password is not None: # found
print("Password: '{}'".format(password.decode('utf-8')))
break
else:
sys.exit('Unable to find password')
print('Runtime: %.5f seconds' % (timer() - start,))
if __name__=="__main__":
main()