Python3 多进程multiprocessing 编程之共享数据使用 与注意事项

目前处理了大概几十万个数据的计算,然后再刷新数据,耗时很严重,使用起来什么卡顿,这里学习使用一下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.

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值