编辑:我使用的是Python 3.5.0,因此map()
将返回迭代器而不是list
,这与Python 2.x不同
我有一个单元列表,我在所有这些单元上调用REST api来返回有关它们的更多数据。我使用map()
来执行此操作,但是当我尝试将该地图转换为列表时,程序会挂起并且不会继续(当我运行它并调试它时)
data = list(map(lambda product: client.request(units_url + "/" + product), units))
起初我认为这可能是一个很快调用api的问题,但是当我手动遍历地图(不将其转换为列表)并打印时,它就可以了:
data = map(lambda product: client.request(units_url + "/" + product), units)
for item in data:
print(item) # <-- this works just fine for the entire map
任何人都知道我为什么会这样做?
答案 0 :(得分:2)
当你list
- 如果是map
时,这意味着每个请求都是按顺序发送的,等待完成,然后存储到生成的list
。如果您要分派1000个请求,这意味着每个请求必须在list
构建之前逐个完成,并且您会看到第一个结果;它是完全同步的。
您可以在直接map
迭代案例中立即获得结果(几乎),因为它一次只生成一个请求;而不是等待1000个请求,它等待1,你处理该结果,然后等待另一个,等等。
如果目标是最小化延迟,请查看multiprocessing.Pool.imap
(或multiprocessing.dummy
中实现的池的基于线程的版本;线程可以是并行网络I / O请求的理想选择并赢得& #39; t要求IPC的酸洗数据)。使用Pool
的{{1}},map
或imap
方法(根据您的需要选择一种方法),将异步调度请求,其中几个时间(取决于您选择的工人数量)。如果您绝对必须拥有imap_unordered
,list
通常会更快地构建它;如果您可以直接进行迭代并且不关心结果的排序,Pool.map
将以工作人员可以获得的结果尽可能快地获得结果,无论他们满意的顺序如何。Pool.imap_unordered
没有map
没有获得任何神奇的性能优势(列表理解通常会更快地运行),所以使用Pool
。
最快结果的简单示例代码:
Pool
如果您确实需要,可以使用import multiprocessing.dummy as multiprocessing # Import thread based version of library; for network I/O should work fine
with multiprocessing.Pool(8) as pool: # Pool of eight worker threads
for item in pool.imap_unordered(lambda product: client.request(units_url + "/" + product), units):
print(item)
并存储到真实的Pool.map
,并假设您有足够的带宽来运行8个并行请求(或者您配置池的工作人员数量很多) ,应该(大致)将完成list
的时间除以8。
答案 1 :(得分:-1)
比以前更好的答案。查看this link。在答案的底部附近,它可以很好地分析你为什么要真正使用列表理解。
data = [client.request(units_url +“/”+ product)for product in units]