laixintao / python-parallel-programming-cookbook-cn

📖《Python Parallel Programming Cookbook》中文版
http://python-parallel-programmning-cookbook.readthedocs.io/
1.49k stars 93 forks source link

勘误4.6中的代码 #74

Closed Sinon02 closed 4 years ago

Sinon02 commented 4 years ago

第四章 6.使用Asyncio和Futures中

# -*- coding: utf-8 -*-

"""
Asyncio.Futures -  Chapter 4 Asynchronous Programming
"""
import asyncio
import sys

@asyncio.coroutine
def first_coroutine(future, N):
    """前n个数的和"""
    count = 0
    for i in range(1, N + 1):
        count = count + i
    yield from asyncio.sleep(4)
    future.set_result("first coroutine (sum of N integers) result = " + str(count))

@asyncio.coroutine
def second_coroutine(future, N):
    count = 1
    for i in range(2, N + 1):
        count *= i
    yield from asyncio.sleep(3)
    future.set_result("second coroutine (factorial) result = " + str(count))

def got_result(future):
   print(future.result())

if __name__ == "__main__":
   N1 = int(sys.argv[1])
   N2 = int(sys.argv[2])
   loop = asyncio.get_event_loop()
   future1 = asyncio.Future()
   future2 = asyncio.Future()
   tasks = [
       first_coroutine(future1, N1),
       second_coroutine(future2, N2)]
   future1.add_done_callback(got_result)
   future2.add_done_callback(got_result)
   loop.run_until_complete(asyncio.wait(tasks))
   loop.close()

该代码的输出为:

$ python asy.py 1 1                                                                      
second coroutine (factorial) result = 1
first coroutine (sum of N integers) result = 1
$ python asy.py 2 2                                                                      
second coroutine (factorial) result = 2
first coroutine (sum of N integers) result = 3
$ python asy.py 3 3                                                                      
second coroutine (factorial) result = 6
first coroutine (sum of N integers) result = 6
$python asy.py 4 4                                                                      
second coroutine (factorial) result = 24
first coroutine (sum of N integers) result = 10

而不是原文中的:

$ python asy.py 1 1
first coroutine (sum of N integers) result = 1
second coroutine (factorial) result = 1
$ python asy.py 2 2
first coroutine (sum of N integers) result = 3
second coroutine (factorial) result = 2
$ python asy.py 3 3
first coroutine (sum of N integers) result = 6
second coroutine (factorial) result = 6
$ python asy.py 4 4
first coroutine (sum of N integers) result = 10
second coroutine (factorial) result = 24

我查看了原文,估计是作者写反了两个sleep的数字,可以考虑改为:

# -*- coding: utf-8 -*-

"""
Asyncio.Futures -  Chapter 4 Asynchronous Programming
"""
import asyncio
import sys

@asyncio.coroutine
def first_coroutine(future, N):
    """前n个数的和"""
    count = 0
    for i in range(1, N + 1):
        count = count + i
    yield from asyncio.sleep(3)
    future.set_result("first coroutine (sum of N integers) result = " + str(count))

@asyncio.coroutine
def second_coroutine(future, N):
    count = 1
    for i in range(2, N + 1):
        count *= i
    yield from asyncio.sleep(4)
    future.set_result("second coroutine (factorial) result = " + str(count))

def got_result(future):
   print(future.result())

if __name__ == "__main__":
   N1 = int(sys.argv[1])
   N2 = int(sys.argv[2])
   loop = asyncio.get_event_loop()
   future1 = asyncio.Future()
   future2 = asyncio.Future()
   tasks = [
       first_coroutine(future1, N1),
       second_coroutine(future2, N2)]
   future1.add_done_callback(got_result)
   future2.add_done_callback(got_result)
   loop.run_until_complete(asyncio.wait(tasks))
   loop.close()

对于新版Python3,也可写成:

# -*- coding: utf-8 -*-

"""
Asyncio.Futures -  Chapter 4 Asynchronous Programming
"""
import asyncio
import sys

async def first_coroutine(future, N):
    """前n个数的和"""
    count = 0
    for i in range(1, N + 1):
        count = count + i
    await asyncio.sleep(3)
    future.set_result("first coroutine (sum of N integers) result = " + str(count))

async def second_coroutine(future, N):
    count = 1
    for i in range(2, N + 1):
        count *= i
    await asyncio.sleep(4)
    future.set_result("second coroutine (factorial) result = " + str(count))

def got_result(future):
   print(future.result())

if __name__ == "__main__":
   N1 = int(sys.argv[1])
   N2 = int(sys.argv[2])
   loop = asyncio.get_event_loop()
   future1 = asyncio.Future()
   future2 = asyncio.Future()
   tasks = [
       first_coroutine(future1, N1),
       second_coroutine(future2, N2)]
   future1.add_done_callback(got_result)
   future2.add_done_callback(got_result)
   loop.run_until_complete(asyncio.wait(tasks))
   loop.close()

测试环境: Python 3.7.4 Microsoft Windows 家庭版[版本 10.0.18362.592]

Sinon02 commented 4 years ago

我看到之前已经有pull request了#66,但是目前版本的代码仍是错误的,可能是版本问题。

laixintao commented 4 years ago

谢谢,这个太奇怪了,我已经合并了,但是发现代码库中没有这个 commit

https://github.com/laixintao/python-parallel-programming-cookbook-cn/pull/66/commits/0c4823a73188d2c360e0ba39fa2e82411582adfd

laixintao commented 4 years ago

Thanks 这个 commit 神奇的丢失了,我重新apply了那位作者的pr,现在应该好了。

https://python-parallel-programmning-cookbook.readthedocs.io/zh_CN/latest/chapter4/06_Dealing_with_Asyncio_and_Futures.html

Please check

Sinon02 commented 4 years ago

ok,感谢大佬的翻译~