async and await
- 解决的问题
can do more things at once
can't make db / io network faster - CPU VS I/O
- synchronous vs asynchronous
- parallelism and concurrency
what we have
thread -> the GIL
processes
concurrent.futures
cpu limit
io multi cutting
async -> io and item can cut and solo item needs some time
https://www.youtube.com/watch?v=iLHRZ8VONsE
https://www.youtube.com/watch?v=tSLDcRkgTsY
a style of concurrent programe
do multiple things at once at python
multiple processes
- the os does all the multi-tasking work
- only option for multi-core concurrency
multiple threads - the os does all the multi-tasking work
- in cpython, the GIL prevents multi-core concerrency
asynchronous programming - no os intervention
- one process, one thread
synchronous chess exhibition -> 一个人和多个人下棋,走动
python 3.7.3 documentation
import asyncio
async def main():
print('hello...')
await asyncio.sleep(3)
print('...world ')
asyncio.run(main()) # RuntimeError: asyncio.run() cannot be called from a running event loop, jupyter is already running an event loop
await main()
# 会阻塞
import asyncio
import time
async def say_after(delay, what):
await asyncio.sleep(delay)
print(what)
async def main():
print(f"started at {time.strftime('%X')}")
await say_after(2, 'hello')
await say_after(2, 'world')
print(f"finished at {time.strftime('%X')}")
# asyncio.run(main())
await main() # 同步的
# task 异步
async def main():
task1 = asyncio.create_task(say_after(2, 'hello'))
task2 = asyncio.create_task(say_after(2, 'hello'))
print(f"started at {time.strftime('%X')}")
await task1
await task2
print(f"finished at {time.strftime('%X')}")
await main()
# running tasks concurrently, awaitable asyncio.gather() 异步,使用gather自动任务调度
# There are three main types of awaitable objects: coroutines, Tasks, and Futures.
import asyncio
async def factorial(name, number):
f = 1
for i in range(2, number + 1):
print(f"task {name}: compute factorial({i})")
await asyncio.sleep(1)
f *= i
print(f"task {name}: factorial({number}) = {f}")
async def main():
await asyncio.gather(
factorial('A', 2),
factorial('B', 3),
factorial('C', 4)
)
await main()
youtube 链接 :
笔记链接:https://osf.io/w8u26/
import time
import asyncio
def is_prime(x):
return not any(x//i == x/i for i in range(x-1, 1, -1))
async def highest_prime_below(x):
print('Highest prime below %d' % x)
for y in range(x-1, 0, -1):
if is_prime(y):
print('→ Highest prime below %d is %d' % (x, y))
return y
await asyncio.sleep(0.01)
return None
async def main():
t0 = time.time()
await asyncio.wait( [
highest_prime_below(100000),
highest_prime_below(10000),
highest_prime_below(1000)
] )
t1 = time.time()
print('Took %.2f ms' % (1000*(t1-t0)))
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
threading
import threading
def countdown():
x = 10000000
while x > 0:
x -= 1
def do_threading():
thread_1 = threading.Thread(target=countdown())
thread_2 = threading.Thread(target=countdown())
thread_1.start()
thread_2.start()
thread_1.join()
thread_2.join()
def run_implementation():
countdown()
countdown()
# 使用线程几乎没有什么用
# what is I/O bound
multiprocessing
import multiprocessing
def run_multiprocese():
process_1 = multiprocessing.Process(target=countdown)
process_2 = multiprocessing.Process(target=countdown)
process_1.start()
process_2.start()
process_1.join()
process_2.join()
以上:https://hackernoon.com/concurrent-programming-in-python-is-not-what-you-think-it-is-b6439c3f3e6a
threadpool
Python标准库为我们提供了threading和multiprocessing模块编写相应的多线程/多进程代码,但是当项目达到一定的规模,
频繁创建/销毁进程或者线程是非常消耗资源的.
从Python3.2开始,标准库为我们提供了concurrent.futures模块,它提供了ThreadPoolExecutor和ProcessPoolExecutor两个类,
实现了对threading和multiprocessing的进一步抽象,对编写线程池/进程池提供了直接的支持。
from concurrent.futures import ProcessPoolExecutor
import time
def return_future_result(message):
time.sleep(2)
return message
pool = ProcessPoolExecutor(max_workers=2)
future1 = pool.submit(return_future_result, ("hello"))
future2 = pool.submit(return_future_result, ("world"))
print(future1.done())
time.sleep(3)
print(future2.done())
print(future1.result())
print(future2.result())
from concurrent.futures import ThreadPoolExecutor
import time
def return_future_result(message):
time.sleep(2)
return message
pool = ThreadPoolExecutor(max_workers=2) # 创建一个最大可容纳2个task的线程池
future1 = pool.submit(return_future_result, ("hello")) # 往线程池里面加入一个task
future2 = pool.submit(return_future_result, ("world")) # 往线程池里面加入一个task
print(future1.done()) # 判断task1是否结束
time.sleep(3)
print(future2.done()) # 判断task2是否结束
print(future1.result()) # 查看task1返回的结果
print(future2.result()) # 查看task2返回的结果