目前处理了大概几十万个数据的计算,然后再刷新数据,耗时很严重,使用起来什么卡顿,这里学习使用一下python的多进程编程。python由于有着GIL全局解释锁,多线程的实际效果并不是很明显,尤其是在计算量比较大的情况,毕竟python也不是为计算而设计的。
模块
这里使用的是python的多进程编程模块:multiprocessing,使用起来还是比较方便的。为了不在一核冒烟,多核围观!加油啊!
共享内存
共享内存则是为进程使用的,主要有Value,Array,Manager三个可以使用。
1. Value和Array的使用类似,但是Value是创建一个变量大小的共享内存,而Array则是创建一个数组大小的共享内存。如下:
from multiprocessing import Process, Array,Value
money = Value('i',10) #这个是创建一个int类型的共享内存变量
money = Array('l', 10) #这个是创建一个long int类型的数组共享内存
Value:细节暂时不讲
Array:这里讲一个保存和读取python字符串的方法。本来是可以使用下面的Manager的,但是不知道为什么Manager一定义就会弹框报错.
字符串处理:
#首先创建一个字符数组并将数据写入:
sysparam = "hello world"
testArray = Array('u', 500) #创建一个共享数组
for i in range(len(sysparam)): #遍历写值
testArray[i] = sysparam[i]
testArray[i+1] = '$' #添加一个结束标志,这里得是字符串中不可能存在的才行
#另外一边进行读取:
strPath = ""
for i in range(0,500):
if argslist[i] =='$':
break
else:
strPath += argslist[i]
2.Manager
这个共享内存可以创建python的一些专属类型,dict,list queue。使用更加方便,但是据说速度好像比上面的慢一些,具体我没有进行测试了。
from multiprocessing import Process,Manager
import os,time
def f(l):
l.append("123")
if __name__ == '__main__':
manager = Manager()
lo= manager.list()
lo.append(2)
p = Process(target=f,args=(lo,))
p.start()
print(lo)
time.sleep(0.1)
print(lo)
简单测试例子
from multiprocessing import Process, Array
def f(a,b):
a[1] = 3
b[1] = 4
if __name__ == '__main__':
arr = Array('l', 10)
arr1 = Array('d', 10)
p = Process(target=f, args=(arr,arr1))
p.start()
p.join()
print(arr[1],arr1[1])
打印反馈为:
3 4.0
这里是等待p线程执行结束(join)才进行打印,如果删除p.join()语句,则不会立刻进行赋值为3 和4.0的。
注意事项
Array与list的互相赋值
array共享变量赋值到list:
arrayvar = Array('l',10)
list = list(arrayvar)
list到array:
arrayvar = Array('l',10)
arrayvar = list #大小必须一样
arrayvar[1:2] = [1] #部分赋值大小也要一样
Pyinstaller的陷阱
这里最坑的就是打包之后,调用Process()来创建其他进程,最后竟然再次打开了自己?懵逼啊、
这里多谢:https://blog.csdn.net/xiong_big/article/details/54614231+https://github.com/pyinstaller/pyinstaller/wiki/Recipe-Multiprocessing
有坑就得查,谢谢大佬帮我填坑。
只要添加这么一个freeze_support()就OK了,如果你还不行?管我什么事,我已经开心地前进了~
from multiprocessing import Process, freeze_support
if __name__ == '__main__':
freeze_support() #from multiprocessing
未处理问题
1.EOFError问题:
在python2.7 window上使用时:
import multiprocessing
s = multiprocessing.Manager()
出错:
File "D:XXXX/XXXXX.py", line XXX, in <module>
s = multiprocessing.Manager()
File "C:\Python27\lib\multiprocessing\__init__.py", line 99, in Manager
m.start()
File "C:\Python27\lib\multiprocessing\managers.py", line 528, in start
self._address = reader.recv()
EOFError
全部注释,将其他已经使用的一些模块注释掉才能使用,Google只搜到一个类似的解释,但是无法解决我的问题,但是好像是可以使用Value,Array()的。附上搜到的解释:
You can work around this by using an absolute import for OtherCustomClass:
from base_module import OtherCustomClass
I'm not exactly sure why, but it seems that when multiprocessing spawns a new process and imports your __main__, it's not able to handle the implicit relative import you're using with OtherCustomClass. If you explicitly import it from base_module, it works fine. My guess is that the spawned child process is not recognized as being part of the base_module package, so the implicit import fails, but that's just a guess.
Note that you shouldn't be using implicit relative imports anyway (they're altogether removed from Python 3), so switching to an absolute import isn't a bad thing.