Python的多线程与多进程实践
最近要产生大量的”假“的电话号码,所以就写了一个自动产生电话号码程序,产生了一百万条数据,然后把数据放到一个文件中。
死跑版:
# -*- coding: utf-8 -*- # 以下是中国的手机号码分段情况 # 新联通 (中国联通+中国网通)手机号码开头数字 130、131、132、145、 # 155、156、185、186 # 新移动 (中国移动+中国铁通)手机号码开头数字 134、135、136、137、 # 138、139、147、150、151、152、157、158、159、182、183、187、188 # 新电信 (中国电信+中国卫通)手机号码开头数字 133、153、189、180 # this script generates telephone numbers in mobile_china, unicom_china,tele_china import random from random import choice import time# mobile info mobile_china = [‘134‘,‘135‘,‘136‘,‘137‘,‘138‘,‘139‘,‘147‘,‘150‘,‘151‘,‘152‘,‘157‘,‘158‘,‘159‘,‘182‘,‘183‘,‘187‘,‘188‘ ] unicom_china = [‘130‘,‘131‘,‘132‘,‘145‘,‘155‘,‘156‘,‘185‘,‘186‘] tele_china = [‘133‘,‘153‘,‘189‘,‘180‘] # the heading three numbers of a telephone number all_three = mobile_china + unicom_china + tele_china # the tailing eight numbers of a telephone number all_eight = 99999999 # 1 million -- the total counts of telephone number # 100 million records is too much for my computer Max = 1000000 def telenum_gen(): # create a file tele_book = open(‘tele_book_solo.txt‘,‘w‘) for i in xrange(Max): three = choice(all_three) eight = str(random.randint(0,all_eight)).rjust(8,‘0‘) tele_num = three + eight print "now the %r th record is %r " %(i,tele_num) tele_book.write(tele_num+"\n") tele_book.close() # begin time start = time.clock() telenum_gen() # end time end = time.clock() print "Running time is %d seconds." %(end-start)
算法很简单,把所有可能的中国联通,中国移动,还有中国电信的前三位号码放到一个列表中,后面八位随机数产生,然后二者拼接成字符串即可。
但是这个运行时间太慢了,运行了4000多秒。如果要产生1亿条数据,计算机直接挂掉了。
于是就考虑,能不能使用多线程或者多进程呢?
于是,就有了多线程版本的电话号码生成器:
多线程版:
# -*- coding: utf-8 -*- # 以下是中国的手机号码分段情况 # 新联通 (中国联通+中国网通)手机号码开头数字 130、131、132、145、 # 155、156、185、186 # 新移动 (中国移动+中国铁通)手机号码开头数字 134、135、136、137、 # 138、139、147、150、151、152、157、158、159、182、183、187、188 # 新电信 (中国电信+中国卫通)手机号码开头数字 133、153、189、180 # this script generates telephone numbers in mobile_china, unicom_china,tele_china import random from random import choice import time import threading # mobile info mobile_china = [‘134‘,‘135‘,‘136‘,‘137‘,‘138‘,‘139‘,‘147‘,‘150‘,‘151‘,‘152‘,‘157‘,‘158‘,‘159‘,‘182‘,‘183‘,‘187‘,‘188‘ ] unicom_china = [‘130‘,‘131‘,‘132‘,‘145‘,‘155‘,‘156‘,‘185‘,‘186‘] tele_china = [‘133‘,‘153‘,‘189‘,‘180‘] # the heading three numbers of a telephone number all_three = mobile_china + unicom_china + tele_china # the tailing eight numbers of a telephone number all_eight = 99999999 # 1 million -- the total counts of telephone number # 100 million records is too much for my computer Max = 1000000 worker_num = 5 def telenum_gen(file): split_work = Max/worker_num for i in xrange(split_work): three = choice(all_three) eight = str(random.randint(0,all_eight)).rjust(8,‘0‘) tele_num = three + eight file.write(tele_num+"\n") print "now the %r th record is %r " %(i,tele_num) if __name__ == ‘__main__‘: # begin time start = time.clock() threads = [] tele_book = open(‘tele_book_thread.txt‘,‘w‘) for x in xrange(worker_num): threads.append(threading.Thread(target=telenum_gen,args=(tele_book,))) #begin to work for worker in threads: worker.start() for worker in threads: worker.join() tele_book.close() # end time end = time.clock() print "Running time is %d seconds." %(end-start)
产生了5个线程,共同对同一个文件做写入操作。
结果,运行时间要比直接产生还要慢,我实验了10万条数据,慢了20秒左右。
于是,又想,是不是多进程会更好一点呢?就查找资料,写了多进程版本的:
多进程版:
# -*- coding: utf-8 -*- # 以下是中国的手机号码分段情况 # 新联通 (中国联通+中国网通)手机号码开头数字 130、131、132、145、 # 155、156、185、186 # 新移动 (中国移动+中国铁通)手机号码开头数字 134、135、136、137、 # 138、139、147、150、151、152、157、158、159、182、183、187、188 # 新电信 (中国电信+中国卫通)手机号码开头数字 133、153、189、180 # this script generates telephone numbers in mobile_china, unicom_china,tele_china import random from random import choice import time import multiprocessing from multiprocessing import Process # mobile info mobile_china = [‘134‘,‘135‘,‘136‘,‘137‘,‘138‘,‘139‘,‘147‘,‘150‘,‘151‘,‘152‘,‘157‘,‘158‘,‘159‘,‘182‘,‘183‘,‘187‘,‘188‘ ] unicom_china = [‘130‘,‘131‘,‘132‘,‘145‘,‘155‘,‘156‘,‘185‘,‘186‘] tele_china = [‘133‘,‘153‘,‘189‘,‘180‘] # the heading three numbers of a telephone number all_three = mobile_china + unicom_china + tele_china # the tailing eight numbers of a telephone number all_eight = 99999999 # 1 million -- the total counts of telephone number # 100 million records is too much for my computer Max = 100000 worker_num = 5 # input worker def telenum_gen(queue): split_work = Max/worker_num for i in xrange(split_work): three = choice(all_three) eight = str(random.randint(0,all_eight)).rjust(8,‘0‘) tele_num = three + eight queue.put(tele_num) print "now the %r th record is %r " %(i,tele_num) # output worker def write_telenum(queue): split_work = Max/worker_num tele_book = open(‘tele_book_process.txt‘,‘a‘) for i in xrange(split_work): tele_num = queue.get() tele_book.write(tele_num+"\n") tele_book.close() if __name__ == ‘__main__‘: print "author: YQ" # begin time start = time.clock() # define input worker list and output worker list of a queue input_workers = [] output_workers = [] lock = multiprocessing.Lock() # To prevent file exception queue = multiprocessing.Queue(-1) # open a file # input process for x in xrange(worker_num): process = multiprocessing.Process(target=telenum_gen,args=(queue,)) process.start() input_workers.append(process) for x in xrange(worker_num): process = multiprocessing.Process(target=write_telenum,args=(queue,)) process.start() output_workers.append(process) #begin to work print "this is the length of input workers:",len(input_workers) for p in input_workers: p.join() queue.close() # No more object will come, close the queue # write_telenum(queue,tele_book) for p in output_workers: p.join() # end time end = time.clock() print "Running time is %d seconds." %(end-start)
做成模式类似于生产者和消费者,一些进程产生数据,放到队列中;另外的一些进程读取数据,并写入到文件中。
由于每个进程都有自己独立的内存空间,所以对消费者进程来讲,不能像线程那样,共享一个文件的句柄,每个进程只能依次执行打开文件,写入,关闭的操作。
运行的结果,依然没有任何起色,与线程版本的运行时间差不多。
总结:
就我的应用场景来说,完全没有必要进行多进程或者多线程,有没有密集的IO操作,没有阻塞,使用多进程或者多线程反而拖累了程序的运行速度。
参考:
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。