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
是如何实现的中学到很多东西,但对于大多数人来说,这些低级知识是毫无用处的。