GVKun编程网logo

使用multiprocessing.Manager.list而不是真实列表会使计算耗时

7

对于想了解使用multiprocessing.Manager.list而不是真实列表会使计算耗时的读者,本文将是一篇不可错过的文章,并且为您提供关于Appium-multiprocessing.poo

对于想了解使用multiprocessing.Manager.list而不是真实列表会使计算耗时的读者,本文将是一篇不可错过的文章,并且为您提供关于Appium - multiprocessing.pool.MaybeEncodingError-【 “Can’t pickle local object ‘PoolManager.__init...、multiprocessing--强大Manage、multiprocessing.Manager()dict()setdefault()是否损坏?、multiprocessing.Manager()。dict()。setdefault()是否损坏?的有价值信息。

本文目录一览:

使用multiprocessing.Manager.list而不是真实列表会使计算耗时

使用multiprocessing.Manager.list而不是真实列表会使计算耗时

我想尝试multiprocessing从本示例开始的不同使用方式:

$ cat multi_bad.py 
import multiprocessing as mp
from time import sleep
from random import randint

def f(l,t):
#   sleep(30)
    return sum(x < t for x in l)

if __name__ == '__main__':
    l = [randint(1,1000) for _ in range(25000)]
    t = [randint(1,1000) for _ in range(4)]
#   sleep(15)
    pool = mp.Pool(processes=4)
    result = pool.starmap_async(f,[(l,x) for x in t])
    print(result.get())

这里l是一个列表,当生成4个进程时,该列表将被复制4次。为了避免这种情况,文档页面提供了使用队列,共享数组或使用创建的代理对象的信息multiprocessing.Manager。对于最后一个,我更改了的定义l

$ diff multi_bad.py multi_good.py 
10c10,11
<     l = [randint(1,1000) for _ in range(25000)]
---
>     man = mp.Manager()
>     l = man.list([randint(1,1000) for _ in range(25000)])

结果看起来仍然正确,但是执行时间却大大增加,以至于我做错了什么:

$ time python multi_bad.py 
[17867,11103,2021,17918]

real    0m0.247s
user    0m0.183s
sys 0m0.010s

$ time python multi_good.py 
[3609,20277,7799,24262]

real    0m15.108s
user    0m28.092s
sys 0m6.320s

文档确实说这种方法比共享数组要慢,但这感觉很不对。我也不确定如何配置此文件,以获取有关正在发生的事情的更多信息。我想念什么吗?

PS与共享数组,我得到的时间低于0.25s。

PPS这是在Linux和Python 3.3上。

Appium - multiprocessing.pool.MaybeEncodingError-【 “Can’t pickle local object ‘PoolManager.__init...

Appium - multiprocessing.pool.MaybeEncodingError-【 “Can’t pickle local object ‘PoolManager.__init...

公司同事学习自动化新装环境后,run多进程测试用例时出错:

multiprocessing.pool.MaybeEncodingError: Error sending result: ’<appium.webdriver.webdriver.WebDriver (session=“261019ae-3776-4a78-aa2c-b24bb64ec62e”)>’. Reason: ’AttributeError(“Can’t pickle local object ‘PoolManager.__init__.<locals>.<lambda>‘“)’

 

同一份代码,我本地并没有这种情况 

 

在网上搜索到三种方法: 

1.用线程替换进程
2.可以使用copy_reg来规避上面的异常.
3.dill 或pathos.multiprocesssing :use ''import pathos.multiprocesssing'', instead of ''import multiprocessing''. pathos.multiprocessing is a fork of multiprocessing that uses dill. dill can serialize almost anything in python, so you are able to send a lot more around in parallel.

 

最开始采用了方法3:use ''import pathos.multiprocesssing'', instead of ''import multiprocessing'' ,然后程序并不在抛出该错误,但是启动case后,appium启动driver后便不在干活(使用两个进程分别在不同端口启动driver),appium log没有错误,pycharm也一直转转转卡在那不去执行find element, 所以还是还原到使用import multiprocessing

 

最终解决方案如下:

 

1. mac裡面的python都刪乾淨
2. 用pyenv裝python 3.5.2
3. 執行multi process case script
4. 把該裝的selenium, Pillow, requests裝一裝
5. 最後一步降级appium-python-client : pip install appium-python-client==0.25 (这个是重点,可以忽略其他步骤直接降级版本,这里是因为需要才重装, 当然笔者local的0.31版本也可以的,就是最新版(0.43)有问题)
6. 成功!

 

multiprocessing--强大Manage

multiprocessing--强大Manage

''''''
multiprocessing--强大Manage
''''''
from multiprocessing import Manager, Process


def worker(dt,lt):
    for i in range(10):
        key = "args" + str(i)
        dt[key] = i*i
    lt += [x for x in range(10)] # 两个列表相加

if __name__ == ''__main__'':
    manager = Manager()
    dt = manager.dict()
    lt = manager.list()
    p = Process(target=worker,args=(dt,lt))
    p.start()
    p.join(timeout=3)  #等待子进程执行完
    print(dt)
    print(lt)

multiprocessing.Manager()dict()setdefault()是否损坏?

multiprocessing.Manager()dict()setdefault()是否损坏?

其后期且可能是愚蠢的部门提出:

>>> import multiprocessing
>>> mgr = multiprocessing.Manager()
>>> d = mgr.dict()
>>> d.setdefault('foo',[]).append({'bar': 'baz'})
>>> print d.items()
[('foo',[])]         <-- Where did the dict go?

鉴于:

>>> e = mgr.dict()
>>> e['foo'] = [{'bar': 'baz'}]
>>> print e.items()
[('foo',[{'bar': 'baz'}])]

版:

>>> sys.version
'2.7.2+ (default,Jan 20 2012,23:05:38) \n[GCC 4.6.2]'

虫子还是臭虫?

编辑:更多相同,在python 3.2上:

>>> sys.version
'3.2.2rc1 (default,Aug 14 2011,21:09:07) \n[GCC 4.6.1]'

>>> e['foo'] = [{'bar': 'baz'}]
>>> print(e.items())
[('foo',[{'bar': 'baz'}])]

>>> id(type(e['foo']))
137341152
>>> id(type([]))
137341152

>>> e['foo'].append({'asdf': 'fdsa'})
>>> print(e.items())
[('foo',[{'bar': 'baz'}])]

字典代理中的列表如何不包含其他元素?

multiprocessing.Manager()。dict()。setdefault()是否损坏?

multiprocessing.Manager()。dict()。setdefault()是否损坏?

其后期且可能是愚蠢的部门提出:

>>> import multiprocessing>>> mgr = multiprocessing.Manager()>>> d = mgr.dict()>>> d.setdefault(''foo'', []).append({''bar'': ''baz''})>>> print d.items()[(''foo'', [])]         <-- Where did the dict go?

鉴于:

>>> e = mgr.dict()>>> e[''foo''] = [{''bar'': ''baz''}]>>> print e.items()[(''foo'', [{''bar'': ''baz''}])]

版:

>>> sys.version''2.7.2+ (default, Jan 20 2012, 23:05:38) \n[GCC 4.6.2]''

虫子还是臭虫?

编辑:更多相同,在python 3.2上:

>>> sys.version''3.2.2rc1 (default, Aug 14 2011, 21:09:07) \n[GCC 4.6.1]''>>> e[''foo''] = [{''bar'': ''baz''}]>>> print(e.items())[(''foo'', [{''bar'': ''baz''}])]>>> id(type(e[''foo'']))137341152>>> id(type([]))137341152>>> e[''foo''].append({''asdf'': ''fdsa''})>>> print(e.items())[(''foo'', [{''bar'': ''baz''}])]

字典代理中的列表如何不包含其他元素?

答案1

小编典典

这是一些非常有趣的行为,我不确定它是如何工作的,但我会弄清楚为什么是这样的行为。

首先,请注意multiprocessing.Manager().dict()不是dict,而是一个DictProxy对象:

>>> d = multiprocessing.Manager().dict()>>> d<DictProxy object, typeid ''dict'' at 0x7fa2bbe8ea50>

DictProxy该类的目的是为您提供一个dict可以在进程之间共享的安全对象,这意味着它必须在常规dict功能之上实现一些锁定。

显然,此处实现的一部分是不允许您直接访问嵌套在内的可变对象DictProxy,因为如果允许,您将能够以绕过所有使DictProxy安全使用的锁定的方式修改共享对象。

这是一些您无法访问可变对象的证据,这与发生的情况类似setdefault()

>>> d[''foo''] = []>>> foo = d[''foo'']>>> id(d[''foo''])140336914055536>>> id(foo)140336914056184

使用普通字典,您会期望d[''foo'']foo指向同一个列表对象,而对一个字典的修改会修改另一个。如您所见,DictProxy由于多处理模块强加了额外的过程安全性要求,因此该类并非如此。

编辑:
以下来自多处理文档的注释阐明了我在上面试图说的内容:


注意:
对dict和list代理中的可变值或项的修改不会通过管理器传播,因为代理无法知道何时修改其值或项。要修改此类项目,可以将修改后的对象重新分配给容器代理:

# create a list proxy and append a mutable object (a dictionary)lproxy = manager.list()lproxy.append({})# now mutate the dictionaryd = lproxy[0]d[''a''] = 1d[''b''] = 2# at this point, the changes to d are not yet synced, but by# reassigning the dictionary, the proxy is notified of the changelproxy[0] = d

根据上述信息,以下是您如何重写原始代码以与一起使用的方法DictProxy

# d.setdefault(''foo'', []).append({''bar'': ''baz''})d[''foo''] = d.get(''foo'', []) + [{''bar'': ''baz''}]

正如Edward Loper在评论中建议的那样,对以上代码进行了编辑,以 get() 代替 setdefault()

今天关于使用multiprocessing.Manager.list而不是真实列表会使计算耗时的分享就到这里,希望大家有所收获,若想了解更多关于Appium - multiprocessing.pool.MaybeEncodingError-【 “Can’t pickle local object ‘PoolManager.__init...、multiprocessing--强大Manage、multiprocessing.Manager()dict()setdefault()是否损坏?、multiprocessing.Manager()。dict()。setdefault()是否损坏?等相关知识,可以在本站进行查询。

本文标签: