Python中的时间密集型收集处理
代码已经大大简化,但应该可以用来说明我的问题Python中的时间密集型收集处理,python,python-3.x,concurrency,parallel-processing,Python,Python 3.x,Concurrency,Parallel Processing,代码已经大大简化,但应该可以用来说明我的问题 S = ('A1RT', 'BDF7', 'CP09') for s in S: if is_valid(s): # very slow! process(s) 我有一个从网站收集的字符串集合。(将定期从站点抓取字符串。)这些字符串中的每一个都需要通过网络针对第三方进行验证。验证过程有时会很慢,这是有问题的。由于上述代码的迭代性质,验证和处理最后一个字符串可能需要一些时间 在Python中有没有合适的方法来并行化上述逻辑?坦
S = ('A1RT', 'BDF7', 'CP09')
for s in S:
if is_valid(s): # very slow!
process(s)
我有一个从网站收集的字符串集合。(将定期从站点抓取字符串。)这些字符串中的每一个都需要通过网络针对第三方进行验证。验证过程有时会很慢,这是有问题的。由于上述代码的迭代性质,验证和处理最后一个字符串可能需要一些时间
在Python中有没有合适的方法来并行化上述逻辑?坦率地说,我不太熟悉并发/并行处理的概念,但在这种情况下它们似乎很有用。想法?并发.futures模块是解决“令人尴尬的并行”问题的好方法,可以很容易地在使用多个进程或单个进程中的多个线程之间切换 在您的情况下,听起来“艰苦的工作”是在网络上的其他机器上完成的,您的主程序将花费大部分时间等待它们交付结果。如果是这样,线程应该可以正常工作。下面是一个完整的可执行玩具示例:
import concurrent.futures as cf
def is_valid(s):
import random
import time
time.sleep(random.random() * 10)
return random.choice([False, True])
NUM_WORKERS = 10 # number of threads you want to run
strings = list("abcdefghijklmnopqrstuvwxyz")
with cf.ThreadPoolExecutor(max_workers=NUM_WORKERS) as executor:
# map a future object to the string passed to is_valid
futures = {executor.submit(is_valid, s): s for s in strings}
# `as_complete()` returns results in the order threads
# complete work, _not_ necessarily in the order the work
# was passed out
for future in cf.as_completed(futures):
result = future.result()
print(futures[future], result)
下面是一次运行的示例输出:
g False
i True
j True
b True
f True
e True
k False
h True
c True
l False
m False
a False
s False
v True
q True
p True
d True
n False
t False
z True
o True
y False
r False
w False
u True
x False
concurrent.futures
处理启动线程、分配任务以及注意线程何时交付结果等所有令人头疼的问题
如上所述,多达10个(
NUM\u WORKERS
)是有效的()
调用可以同时激活as_completed()
在其结果准备好检索时立即返回一个未来的对象,执行器会自动将计算结果的线程交给另一个有效的字符串()
看一看这里的效果。出于好奇,如果“辛苦工作”和等待时间是由于本地计算造成的,会发生什么?是否需要一种不同的方法?若然,原因为何?对于所有的问题,我很抱歉,但我在这方面有点新手。并行处理是一个非常大和复杂的主题,很多书都写过。如果你已经全职做了一年,你仍然是“新手”;-)也就是说,由于全局解释器锁(googleon“pythongil”)的存在,线程对于纯CPython代码中的CPU绑定任务是无效的。在这种情况下,您最好的第一个选择是使用cf的ProcessPoolExecutor
(使用多个进程而不是多个线程,这样GIL就不会成为问题)。啊,非常感谢您的帮助/见解!我得问一下,你个人有没有推荐一些资源来开始这个话题?@kylemart很抱歉插嘴。在深入研究大量的细节之前,我们应该首先非常确定“只是”[CONCURRENT]
系统操作模式(调度)和真正的系统操作模式(并行)的区别。这是不一样的。下一步,没有例外,没有借口,应该知道进行多线程/多进程或任何其他形式的并发处理的成本。在不知道成本的情况下,人们可能会花费巨大的精力在最终比纯处理流程更糟糕的性能上。问错人了。从20世纪80年代开始,我就一直在这样做,当时每个人都通过口碑和眼泪相互学习;-)我不知道现在有什么介绍材料。但好的建议是:除非您想为其他人实现并行处理技巧,否则请坚持使用您的语言提供的最高级别抽象。这就是为什么我引导您使用concurrent.futures
(Python的最高级别并行抽象)。你可以从cf
是如何实现的中学到很多东西,但对于大多数人来说,这些低级知识是毫无用处的。