Python,如何打破多个线程

时间:2014-07-30 19:43:48

标签: python multithreading

我正在阅读我正在阅读的一本书中的一个例子(" 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()

2 个答案:

答案 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)