简体   繁体   English

用于并发的python生成器

[英]python generators for concurrency

I am following slides from Python's guru David Beazley.我正在关注 Python 大师 David Beazley 的幻灯片。 It states "Generators are also used for concurrency. Here is an example:它指出“生成器也用于并发。这是一个例子:

from collections import deque

def countdown(n):
    while n > 0:
        print("T-minus", n)
        yield
        n -=1

def countup(n):
    x = 0
    while x > n:
        print("Up we go", x)
        yield
        x +=1

# instantiate some tasks in a queue
tasks = deque([countdown(10),
               countdown(5),
               countup(20)
               ])

# run a little scheduler
while tasks:
    t = tasks.pop()  # get a task
    try:
        next(t)   # run it until it yields
        tasks.appendleft(t) # reschedule
    except StopIteration:
        pass

Here is the output:这是输出:

T-minus 5
T-minus 10
T-minus 4
T-minus 9
T-minus 3
T-minus 8
T-minus 2
T-minus 7
T-minus 1
T-minus 6
T-minus 5
T-minus 4
T-minus 3
T-minus 2
T-minus 1

The question is how is concurrency introduced by generators and how is it manifesting?问题是生成器是如何引入并发性的,它是如何表现出来的?

This bit of code implements the concept of "green threads", cooperative, userland (as opposed to Preemptive, kernel) threading.这段代码实现了“绿色线程”、协作、用户空间(相对于抢占式、内核)线程的概念。

The "threads" are the generators, each function with yeild or yield from in it. “线程”是生成器,每个函数都包含yeildyield from The scheduler lives, obviously, inside the if __name__ == '__main__': bit.显然,调度程序存在于if __name__ == '__main__':位中。

So, lets imagine we have not generators but regular lists, and each list has in it, a sequence of functions.因此,假设我们没有生成器,而是常规列表,并且每个列表中都有一个函数序列。

def doThis(): pass
def sayThis(): pass
def doThat(): pass
...

myThread = [doThis, doThat, doAnother]
yourThread = [sayThis, sayThat, sayAnother]

We could run all of the functions in order:我们可以按顺序运行所有函数:

for thread in [myThread, yourThread]:
    for stmt in thread:
        stmt()

Or we could do them in some other order:或者我们可以按其他顺序进行:

for myStmt, yourStmt in zip(myThread, yourThread):
    myStmt()
    yourStmt()

In the first "scheduler", we exhaust the first thread, and then proceed to the second thread.在第一个“调度器”中,我们耗尽了第一个线程,然后再进行第二个线程。 In the second scheduler, we interleave statements out of both threads, first mine, then yours, then back to mine.在第二个调度程序中,我们将两个线程中的语句交织在一起,首先是我的,然后是你的,然后是我的。

It's because we are interleaving "statements" across multiple "threads" before exausting those threads that we can say that the second scheduler gives concurrency.这是因为我们在耗尽那些线程之前在多个“线程”中交错“语句”,我们可以说第二个调度程序提供并发性。

Note that concurrency doesn't neccesarily mean parallelism.请注意,并发并不一定意味着并行。 It's not simultaneous execution, just overlapping.这不是同时执行,只是重叠。

Here is an example to clarify:这是一个澄清的例子:

from collections import deque

def coro1():
    for i in range(1, 10):
        yield i

def coro2():
    for i in range(1, 10):
        yield i*10

print('Async behaviour'.center(60, '#'))
tasks = deque()
tasks.extend([coro1(), coro2()])

while tasks:
    task = tasks.popleft()  # select and remove a task (coro1/coro2).
    try:
        print(next(task))
        tasks.append(task)  # add the removed task (coro1/coro2) for permutation.
    except StopIteration:
        pass

Out:出去:

######################Async behaviour#######################
1
10
2
20
3
30
4
40
5
50
6
60
7
70
8
80
9
90

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM