我正在阅读我正在阅读的一本书中的一个例子(" Violent Python")。它是从字典创建一个zip文件密码破解程序。我有两个问题。首先,它说我要在代码中编写它以提高性能,但是当我计时时(我知道time.time()对于计时并不好),大约有12秒的差异支持不进行线程化。这是因为启动线程需要更长的时间吗?第二,如果我没有线程,我可以通过打印结果并输入语句exit(0)找到正确的值后立即中断。有没有办法使用线程获得相同的结果,这样如果我找到我想要的结果,我可以同时结束所有其他线程?
import zipfile
from threading import Thread
import time
def extractFile(z, password, starttime):
try:
z.extractall(pwd=password)
except:
pass
else:
z.close()
print('PWD IS ' + password)
print(str(time.time()-starttime))
def main():
start = time.time()
z = zipfile.ZipFile('test.zip')
pwdfile = open('words.txt')
pwds = pwdfile.read()
pwdfile.close()
for pwd in pwds.splitlines():
t = Thread(target=extractFile, args=(z, pwd, start))
t.start()
#extractFile(z, pwd, start)
print(str(time.time()-start))
if __name__ == '__main__':
main()
答案 0 :(得分:2)
在CPython中,全局解释器锁(“GIL”)强制执行限制,一次只有一个线程可以执行Python字节码。
因此,在此应用程序中,最好使用map
的{{1}}方法,因为每次尝试都与其他尝试无关;
multiprocessing.Pool
这将启动(默认情况下)与计算机具有核心的进程数。如果在import multiprocessing
import zipfile
def tryfile(password):
rv = passwd
with zipfile.ZipFile('test.zip') as z:
try:
z.extractall(pwd=password)
except:
rv = None
return rv
with open('words.txt') as pwdfile:
data = pwdfile.read()
pwds = data.split()
p = multiprocessing.Pool()
results = p.map(tryfile, pwds)
results = [r for r in results if r is not None]
列表用完之前,将继续在这些进程中使用不同的密码运行tryfile()
,请收集结果并将其返回。最后一个列表理解是丢弃pwds
结果。
请注意,可以改进此代码,以便在找到密码后停止关闭None
。在这种情况下,您可能必须使用map
和共享变量。将zipfile加载一次并分享它也是一件好事。
答案 1 :(得分:1)
这段代码很慢,因为python有Global Interpreter Lock,这意味着一次只能执行一个线程。这导致多线程代码比Python中的串行代码运行得慢。如果要创建真正的多线程应用程序,则必须使用Multiprocessing Module.
要突破线程并获取返回值,可以使用os._exit(1)
首先,导入文件顶部的os模块:
import os
然后,将extractFile
功能更改为使用os._exit(1)
:
def extractFile(z, password, starttime):
try:
z.extractall(pwd=password)
except:
pass
else:
z.close()
print('PWD IS ' + password)
print(str(time.time()-starttime))
os._exit(1)