├── .gitignore ├── 1-slow_sync.py ├── 10-long_sync_in_thread.py ├── 11-task_without_await.py ├── 2-basic.py ├── 3-async_httpx.py ├── 4-slow_async.py ├── 5-fast_async.py ├── 6-async_without_gather.py ├── 6.5-about-task.py ├── 7-fib.py ├── 8-cpu-async.py ├── 9-sync_in_async.py ├── Pipfile ├── Pipfile.lock ├── limit_concurrent.py ├── poetry.lock ├── pyproject.toml ├── readme.md ├── server.py ├── test_class.py └── 一学就会的 Python asyncio 基础课.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vscode/ 3 | __pycache__/ 4 | -------------------------------------------------------------------------------- /1-slow_sync.py: -------------------------------------------------------------------------------- 1 | import time 2 | import requests 3 | 4 | 5 | def run_test(): 6 | resp1 = requests.get('http://127.0.0.1:8000/sleep/3').json() 7 | print(resp1) 8 | resp1 = requests.get('http://127.0.0.1:8000/sleep/5').json() 9 | print(resp1) 10 | resp1 = requests.get('http://127.0.0.1:8000/sleep/8').json() 11 | print(resp1) 12 | 13 | 14 | start = time.time() 15 | run_test() 16 | end = time.time() 17 | 18 | print(f'请求3个页面,总共耗时:{end - start}') -------------------------------------------------------------------------------- /10-long_sync_in_thread.py: -------------------------------------------------------------------------------- 1 | import time 2 | import httpx 3 | import asyncio 4 | from concurrent.futures import ThreadPoolExecutor 5 | 6 | 7 | async def request(sleep_time): 8 | async with httpx.AsyncClient(timeout=20) as client: 9 | resp = await client.get(f'http://127.0.0.1:8000/sleep/{sleep_time}') 10 | resp_json = resp.json() 11 | print(resp_json) 12 | 13 | 14 | def sync_calc_fib(n): 15 | if n in [1, 2]: 16 | return 1 17 | return sync_calc_fib(n - 1) + sync_calc_fib(n - 2) 18 | 19 | 20 | def calc_fib(n): 21 | result = sync_calc_fib(n) 22 | print(f'第 {n} 项计算完成,结果是:{result}') 23 | return result 24 | 25 | 26 | async def main(): 27 | start = time.perf_counter() 28 | loop = asyncio.get_event_loop() 29 | with ThreadPoolExecutor(max_workers=4) as executor: 30 | tasks_list = [ 31 | loop.run_in_executor(executor, calc_fib, 36), 32 | asyncio.create_task(request(5)) 33 | ] 34 | await asyncio.gather(*tasks_list) 35 | end = time.perf_counter() 36 | print(f'总计耗时:{end - start}') 37 | 38 | 39 | asyncio.run(main()) 40 | 41 | -------------------------------------------------------------------------------- /11-task_without_await.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | 4 | def fib(n): 5 | if n in [1, 2]: 6 | return 1 7 | return fib(n - 1) + fib(n - 2) 8 | 9 | 10 | async def job1(): 11 | print(1) 12 | print(2) 13 | print(fib(36)) 14 | print(3) 15 | 16 | 17 | async def job2(): 18 | print('job2-1') 19 | print('job2-2') 20 | print('job2-3') 21 | 22 | async def job3(): 23 | print('job3-1') 24 | print('job3-2') 25 | print('job3-3') 26 | 27 | 28 | async def main(): 29 | print('aaaa') 30 | asyncio.create_task(job2()) 31 | asyncio.create_task(job1()) 32 | asyncio.create_task(job3()) 33 | print('bbbb') 34 | print('cccc') 35 | 36 | 37 | asyncio.run(main()) -------------------------------------------------------------------------------- /2-basic.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | 4 | async def i_am_async_func(): 5 | print('我是一个异步函数') 6 | return 'kingname' 7 | 8 | 9 | async def i_will_call_you(): 10 | print('我来调用异步函数') 11 | result = await i_am_async_func() 12 | print('异步函数返回的值是:', result) 13 | 14 | 15 | async def matryoshka(): 16 | print('我去调用那个调用异步函数的异步函数') 17 | await i_will_call_you() 18 | 19 | 20 | asyncio.run(matryoshka()) -------------------------------------------------------------------------------- /3-async_httpx.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import httpx 3 | 4 | 5 | async def request(): 6 | async with httpx.AsyncClient() as client: 7 | response = await client.get('http://127.0.0.1:8000/sleep/3') 8 | result = response.json() 9 | print(result) 10 | 11 | 12 | asyncio.run(request()) -------------------------------------------------------------------------------- /4-slow_async.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import httpx 3 | import time 4 | 5 | 6 | async def request(num): 7 | async with httpx.AsyncClient(timeout=20) as client: 8 | response = await client.get(f'http://127.0.0.1:8000/sleep/{num}') 9 | result = response.json() 10 | print(result) 11 | 12 | 13 | async def main(): 14 | start = time.time() 15 | await request(3) 16 | await request(5) 17 | await request(8) 18 | end = time.time() 19 | print(f'使用协程请求三个网址,耗时:{end - start}') 20 | 21 | 22 | asyncio.run(main()) -------------------------------------------------------------------------------- /5-fast_async.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import httpx 3 | import time 4 | 5 | 6 | async def do_request(sleep_time): 7 | async with httpx.AsyncClient(timeout=20) as session: 8 | resp = await session.get(f'http://127.0.0.1:8000/sleep/{sleep_time}') 9 | print(resp.json()) 10 | 11 | 12 | async def main(): 13 | start = time.time() 14 | task1 = do_request(3) 15 | task2 = do_request(5) 16 | task3 = do_request(8) 17 | task_list = [task1, task2, task3] 18 | await asyncio.gather(*task_list) 19 | end = time.time() 20 | print(f'使用协程请求三个网址,耗时:{end - start}') 21 | 22 | 23 | asyncio.run(main()) -------------------------------------------------------------------------------- /6-async_without_gather.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import httpx 3 | import time 4 | 5 | 6 | async def do_request(sleep_time): 7 | async with httpx.AsyncClient(timeout=20) as session: 8 | resp = await session.get(f'http://127.0.0.1:8000/sleep/{sleep_time}') 9 | print(resp.json()) 10 | 11 | 12 | async def main(): 13 | start = time.time() 14 | task1 = asyncio.create_task(do_request(3)) 15 | task2 = asyncio.create_task(do_request(5)) 16 | task3 = asyncio.create_task(do_request(8)) 17 | await task3 # 用耗时最长的任务防止退出函数 18 | await task1 19 | await task2 20 | # for i in range(10): 21 | # await asyncio.sleep(1) # 如果不知道谁耗时长,也可以用asyncio.sleep 22 | end = time.time() 23 | print(f'使用协程请求三个网址,耗时:{end - start}') 24 | 25 | 26 | asyncio.run(main()) -------------------------------------------------------------------------------- /6.5-about-task.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import httpx 3 | 4 | 5 | async def req(delay): 6 | async with httpx.AsyncClient(timeout=20) as client: 7 | resp = await client.get(f'http://127.0.0.1:8000/sleep/{delay}') 8 | data = resp.json() 9 | print(data) 10 | 11 | 12 | async def job1(): 13 | print('进入job1里面') 14 | print(1) 15 | print(2) 16 | print(3) 17 | print(3) 18 | print(3) 19 | print(3) 20 | print(3) 21 | print(3) 22 | print(3) 23 | print(3) 24 | print(3) 25 | print(3) 26 | print(3) 27 | print(3) 28 | await req(3) 29 | print('job1请求完成') 30 | print(4) 31 | print(5) 32 | print(6) 33 | 34 | 35 | async def job2(): 36 | print('进入 job2') 37 | print('一') 38 | print('二') 39 | print('三') 40 | await req(5) 41 | print('job2 请求完成') 42 | print('四') 43 | print('五') 44 | print('六') 45 | 46 | 47 | async def task_without_await(): 48 | print('瞬间执行1') 49 | print('瞬间执行2') 50 | print('瞬间执行3') 51 | 52 | 53 | async def main(): 54 | print('第1行') 55 | task1 = asyncio.create_task(job1()) 56 | print('第2行') 57 | task5 = asyncio.create_task(task_without_await()) 58 | task2 = asyncio.create_task(job2()) 59 | # await task1 60 | print('第3行') 61 | print('第4行') 62 | print('第5行') 63 | await task2 64 | 65 | 66 | asyncio.run(main()) 67 | -------------------------------------------------------------------------------- /7-fib.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | 4 | def fib(n): 5 | if n in [1, 2]: 6 | return 1 7 | return fib(n - 1) + fib(n - 2) 8 | 9 | 10 | start = time.time() 11 | result = fib(36) 12 | end = time.time() 13 | 14 | print(f'计算斐波拉契数列第36项,耗时:{end - start}') -------------------------------------------------------------------------------- /8-cpu-async.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import httpx 3 | import time 4 | 5 | 6 | async def fib(n): 7 | if n in [1, 2]: 8 | return 1 9 | return await fib(n - 1) + await fib(n - 2) 10 | 11 | 12 | async def do_request(sleep_time): 13 | async with httpx.AsyncClient(timeout=20) as session: 14 | resp = await session.get(f'http://127.0.0.1:8000/sleep/{sleep_time}') 15 | print(resp.json()) 16 | 17 | async def main(): 18 | start = time.time() 19 | task1 = fib(36) 20 | task2 = do_request(5) 21 | await asyncio.gather(task1, task2) 22 | end = time.time() 23 | print(f'强行把 CPU 密集型代码放到 async 中,耗时:{end - start}') 24 | 25 | 26 | asyncio.run(main()) -------------------------------------------------------------------------------- /9-sync_in_async.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import httpx 3 | import time 4 | 5 | 6 | def fib(n): 7 | if n in [1, 2]: 8 | return 1 9 | return fib(n - 1) + fib(n - 2) 10 | 11 | 12 | async def do_request(sleep_time): 13 | async with httpx.AsyncClient(timeout=20) as session: 14 | resp = await session.get(f'http://127.0.0.1:8000/sleep/{sleep_time}') 15 | print(resp.json()) 16 | 17 | 18 | async def run_fib(): 19 | result = fib(36) 20 | print(f'斐波拉契数列第36项是:{result}') 21 | 22 | async def main(): 23 | start = time.time() 24 | task1 = run_fib() 25 | task2 = do_request(5) 26 | await asyncio.gather(task1, task2) 27 | end = time.time() 28 | print(f'在协程中调用耗时的同步函数,耗时:{end - start}') 29 | 30 | 31 | asyncio.run(main()) -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | name = "pypi" 3 | url = "https://pypi.org/simple" 4 | verify_ssl = true 5 | 6 | [dev-packages] 7 | 8 | [packages] 9 | httpx = "*" 10 | 11 | [requires] 12 | python_version = "3.8" 13 | -------------------------------------------------------------------------------- /Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_meta": { 3 | "hash": { 4 | "sha256": "1ef2815b3438b36b86d80e27c2a7b355e1a937478bb6dd489801a1aac9d5329f" 5 | }, 6 | "pipfile-spec": 6, 7 | "requires": { 8 | "python_version": "3.8" 9 | }, 10 | "sources": [ 11 | { 12 | "name": "pypi", 13 | "url": "https://pypi.org/simple", 14 | "verify_ssl": true 15 | } 16 | ] 17 | }, 18 | "default": { 19 | "anyio": { 20 | "hashes": [ 21 | "sha256:929a6852074397afe1d989002aa96d457e3e1e5441357c60d03e7eea0e65e1b0", 22 | "sha256:ae57a67583e5ff8b4af47666ff5651c3732d45fd26c929253748e796af860374" 23 | ], 24 | "markers": "python_full_version >= '3.6.2'", 25 | "version": "==3.3.0" 26 | }, 27 | "certifi": { 28 | "hashes": [ 29 | "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee", 30 | "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8" 31 | ], 32 | "version": "==2021.5.30" 33 | }, 34 | "h11": { 35 | "hashes": [ 36 | "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6", 37 | "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042" 38 | ], 39 | "markers": "python_version >= '3.6'", 40 | "version": "==0.12.0" 41 | }, 42 | "httpcore": { 43 | "hashes": [ 44 | "sha256:b0d16f0012ec88d8cc848f5a55f8a03158405f4bca02ee49bc4ca2c1fda49f3e", 45 | "sha256:db4c0dcb8323494d01b8c6d812d80091a31e520033e7b0120883d6f52da649ff" 46 | ], 47 | "markers": "python_version >= '3.6'", 48 | "version": "==0.13.6" 49 | }, 50 | "httpx": { 51 | "hashes": [ 52 | "sha256:979afafecb7d22a1d10340bafb403cf2cb75aff214426ff206521fc79d26408c", 53 | "sha256:9f99c15d33642d38bce8405df088c1c4cfd940284b4290cacbfb02e64f4877c6" 54 | ], 55 | "index": "pypi", 56 | "version": "==0.18.2" 57 | }, 58 | "idna": { 59 | "hashes": [ 60 | "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a", 61 | "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3" 62 | ], 63 | "version": "==3.2" 64 | }, 65 | "rfc3986": { 66 | "extras": [ 67 | "idna2008" 68 | ], 69 | "hashes": [ 70 | "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835", 71 | "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97" 72 | ], 73 | "version": "==1.5.0" 74 | }, 75 | "sniffio": { 76 | "hashes": [ 77 | "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663", 78 | "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de" 79 | ], 80 | "markers": "python_version >= '3.5'", 81 | "version": "==1.2.0" 82 | } 83 | }, 84 | "develop": {} 85 | } 86 | -------------------------------------------------------------------------------- /limit_concurrent.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import httpx 3 | import time 4 | 5 | @property 6 | async def req(delay, sem): 7 | print(f'请求一个延迟为{delay}秒的接口') 8 | async with sem: 9 | async with httpx.AsyncClient(timeout=20) as client: 10 | resp = await client.get(f'http://127.0.0.1:8000/sleep/{delay}') 11 | result = resp.json() 12 | print(result) 13 | await asyncio.sleep(60) 14 | 15 | 16 | async def main(): 17 | start = time.time() 18 | delay_list = [3, 6, 1, 8, 2, 4, 5, 2, 7, 3, 9, 8] 19 | task_list = [] 20 | sem = asyncio.Semaphore(3) 21 | for delay in delay_list: 22 | task = asyncio.create_task(req(delay, sem)) 23 | task_list.append(task) 24 | await asyncio.gather(*task_list) 25 | 26 | end = time.time() 27 | print(f'一共耗时:{end - start}') 28 | 29 | asyncio.run(main()) 30 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | category = "main" 3 | description = "Async http client/server framework (asyncio)" 4 | name = "aiohttp" 5 | optional = false 6 | python-versions = ">=3.5.3" 7 | version = "3.6.3" 8 | 9 | [package.dependencies] 10 | async-timeout = ">=3.0,<4.0" 11 | attrs = ">=17.3.0" 12 | chardet = ">=2.0,<4.0" 13 | multidict = ">=4.5,<5.0" 14 | yarl = ">=1.0,<1.6.0" 15 | 16 | [package.extras] 17 | speedups = ["aiodns", "brotlipy", "cchardet"] 18 | 19 | [[package]] 20 | category = "main" 21 | description = "Timeout context manager for asyncio programs" 22 | name = "async-timeout" 23 | optional = false 24 | python-versions = ">=3.5.3" 25 | version = "3.0.1" 26 | 27 | [[package]] 28 | category = "main" 29 | description = "Classes Without Boilerplate" 30 | name = "attrs" 31 | optional = false 32 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 33 | version = "20.2.0" 34 | 35 | [package.extras] 36 | dev = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "sphinx-rtd-theme", "pre-commit"] 37 | docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] 38 | tests = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] 39 | tests_no_zope = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"] 40 | 41 | [[package]] 42 | category = "main" 43 | description = "Python package for providing Mozilla's CA Bundle." 44 | name = "certifi" 45 | optional = false 46 | python-versions = "*" 47 | version = "2020.6.20" 48 | 49 | [[package]] 50 | category = "main" 51 | description = "Universal encoding detector for Python 2 and 3" 52 | name = "chardet" 53 | optional = false 54 | python-versions = "*" 55 | version = "3.0.4" 56 | 57 | [[package]] 58 | category = "main" 59 | description = "Composable command line interface toolkit" 60 | name = "click" 61 | optional = false 62 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 63 | version = "7.1.2" 64 | 65 | [[package]] 66 | category = "main" 67 | description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" 68 | name = "fastapi" 69 | optional = false 70 | python-versions = ">=3.6" 71 | version = "0.61.1" 72 | 73 | [package.dependencies] 74 | pydantic = ">=1.0.0,<2.0.0" 75 | starlette = "0.13.6" 76 | 77 | [package.extras] 78 | all = ["requests (>=2.24.0,<3.0.0)", "aiofiles (>=0.5.0,<0.6.0)", "jinja2 (>=2.11.2,<3.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "itsdangerous (>=1.1.0,<2.0.0)", "pyyaml (>=5.3.1,<6.0.0)", "graphene (>=2.1.8,<3.0.0)", "ujson (>=3.0.0,<4.0.0)", "orjson (>=3.2.1,<4.0.0)", "email_validator (>=1.1.1,<2.0.0)", "uvicorn (>=0.11.5,<0.12.0)", "async_exit_stack (>=1.0.1,<2.0.0)", "async_generator (>=1.10,<2.0.0)"] 79 | dev = ["python-jose (>=3.1.0,<4.0.0)", "passlib (>=1.7.2,<2.0.0)", "autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "uvicorn (>=0.11.5,<0.12.0)", "graphene (>=2.1.8,<3.0.0)"] 80 | doc = ["mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=5.5.0,<6.0.0)", "markdown-include (>=0.5.1,<0.6.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.2.0)", "typer (>=0.3.0,<0.4.0)", "typer-cli (>=0.0.9,<0.0.10)", "pyyaml (>=5.3.1,<6.0.0)"] 81 | test = ["pytest (5.4.3)", "pytest-cov (2.10.0)", "pytest-asyncio (>=0.14.0,<0.15.0)", "mypy (0.782)", "flake8 (>=3.8.3,<4.0.0)", "black (19.10b0)", "isort (>=5.0.6,<6.0.0)", "requests (>=2.24.0,<3.0.0)", "httpx (>=0.14.0,<0.15.0)", "email_validator (>=1.1.1,<2.0.0)", "sqlalchemy (>=1.3.18,<2.0.0)", "peewee (>=3.13.3,<4.0.0)", "databases (>=0.3.2,<0.4.0)", "orjson (>=3.2.1,<4.0.0)", "async_exit_stack (>=1.0.1,<2.0.0)", "async_generator (>=1.10,<2.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "aiofiles (>=0.5.0,<0.6.0)", "flask (>=1.1.2,<2.0.0)"] 82 | 83 | [[package]] 84 | category = "main" 85 | description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" 86 | name = "h11" 87 | optional = false 88 | python-versions = "*" 89 | version = "0.11.0" 90 | 91 | [[package]] 92 | category = "main" 93 | description = "Internationalized Domain Names in Applications (IDNA)" 94 | name = "idna" 95 | optional = false 96 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 97 | version = "2.10" 98 | 99 | [[package]] 100 | category = "main" 101 | description = "multidict implementation" 102 | name = "multidict" 103 | optional = false 104 | python-versions = ">=3.5" 105 | version = "4.7.6" 106 | 107 | [[package]] 108 | category = "main" 109 | description = "Data validation and settings management using python 3.6 type hinting" 110 | name = "pydantic" 111 | optional = false 112 | python-versions = ">=3.6" 113 | version = "1.6.1" 114 | 115 | [package.extras] 116 | dotenv = ["python-dotenv (>=0.10.4)"] 117 | email = ["email-validator (>=1.0.3)"] 118 | typing_extensions = ["typing-extensions (>=3.7.2)"] 119 | 120 | [[package]] 121 | category = "main" 122 | description = "Python HTTP for Humans." 123 | name = "requests" 124 | optional = false 125 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 126 | version = "2.24.0" 127 | 128 | [package.dependencies] 129 | certifi = ">=2017.4.17" 130 | chardet = ">=3.0.2,<4" 131 | idna = ">=2.5,<3" 132 | urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" 133 | 134 | [package.extras] 135 | security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] 136 | socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] 137 | 138 | [[package]] 139 | category = "main" 140 | description = "The little ASGI library that shines." 141 | name = "starlette" 142 | optional = false 143 | python-versions = ">=3.6" 144 | version = "0.13.6" 145 | 146 | [package.extras] 147 | full = ["aiofiles", "graphene", "itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests", "ujson"] 148 | 149 | [[package]] 150 | category = "main" 151 | description = "HTTP library with thread-safe connection pooling, file post, and more." 152 | name = "urllib3" 153 | optional = false 154 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" 155 | version = "1.25.11" 156 | 157 | [package.extras] 158 | brotli = ["brotlipy (>=0.6.0)"] 159 | secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] 160 | socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] 161 | 162 | [[package]] 163 | category = "main" 164 | description = "The lightning-fast ASGI server." 165 | name = "uvicorn" 166 | optional = false 167 | python-versions = "*" 168 | version = "0.12.1" 169 | 170 | [package.dependencies] 171 | click = ">=7.0.0,<8.0.0" 172 | h11 = ">=0.8" 173 | 174 | [package.extras] 175 | standard = ["websockets (>=8.0.0,<9.0.0)", "watchgod (>=0.6,<0.7)", "python-dotenv (>=0.13)", "PyYAML (>=5.1)", "httptools (>=0.1.0,<0.2.0)", "uvloop (>=0.14.0)", "colorama (>=0.4)"] 176 | 177 | [[package]] 178 | category = "main" 179 | description = "Yet another URL library" 180 | name = "yarl" 181 | optional = false 182 | python-versions = ">=3.5" 183 | version = "1.5.1" 184 | 185 | [package.dependencies] 186 | idna = ">=2.0" 187 | multidict = ">=4.0" 188 | 189 | [metadata] 190 | content-hash = "150cb07a0fefb2d646d34edd743e535c989c36b3eacff67051ea065cef59d5ac" 191 | python-versions = "^3.8" 192 | 193 | [metadata.files] 194 | aiohttp = [ 195 | {file = "aiohttp-3.6.3-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:1a4160579ffbc1b69e88cb6ca8bb0fbd4947dfcbf9fb1e2a4fc4c7a4a986c1fe"}, 196 | {file = "aiohttp-3.6.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:fb83326d8295e8840e4ba774edf346e87eca78ba8a89c55d2690352842c15ba5"}, 197 | {file = "aiohttp-3.6.3-cp35-cp35m-win32.whl", hash = "sha256:470e4c90da36b601676fe50c49a60d34eb8c6593780930b1aa4eea6f508dfa37"}, 198 | {file = "aiohttp-3.6.3-cp35-cp35m-win_amd64.whl", hash = "sha256:a885432d3cabc1287bcf88ea94e1826d3aec57fd5da4a586afae4591b061d40d"}, 199 | {file = "aiohttp-3.6.3-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:c506853ba52e516b264b106321c424d03f3ddef2813246432fa9d1cefd361c81"}, 200 | {file = "aiohttp-3.6.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:797456399ffeef73172945708810f3277f794965eb6ec9bd3a0c007c0476be98"}, 201 | {file = "aiohttp-3.6.3-cp36-cp36m-win32.whl", hash = "sha256:60f4caa3b7f7a477f66ccdd158e06901e1d235d572283906276e3803f6b098f5"}, 202 | {file = "aiohttp-3.6.3-cp36-cp36m-win_amd64.whl", hash = "sha256:2ad493de47a8f926386fa6d256832de3095ba285f325db917c7deae0b54a9fc8"}, 203 | {file = "aiohttp-3.6.3-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:319b490a5e2beaf06891f6711856ea10591cfe84fe9f3e71a721aa8f20a0872a"}, 204 | {file = "aiohttp-3.6.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:66d64486172b032db19ea8522328b19cfb78a3e1e5b62ab6a0567f93f073dea0"}, 205 | {file = "aiohttp-3.6.3-cp37-cp37m-win32.whl", hash = "sha256:206c0ccfcea46e1bddc91162449c20c72f308aebdcef4977420ef329c8fcc599"}, 206 | {file = "aiohttp-3.6.3-cp37-cp37m-win_amd64.whl", hash = "sha256:687461cd974722110d1763b45c5db4d2cdee8d50f57b00c43c7590d1dd77fc5c"}, 207 | {file = "aiohttp-3.6.3.tar.gz", hash = "sha256:698cd7bc3c7d1b82bb728bae835724a486a8c376647aec336aa21a60113c3645"}, 208 | ] 209 | async-timeout = [ 210 | {file = "async-timeout-3.0.1.tar.gz", hash = "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f"}, 211 | {file = "async_timeout-3.0.1-py3-none-any.whl", hash = "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"}, 212 | ] 213 | attrs = [ 214 | {file = "attrs-20.2.0-py2.py3-none-any.whl", hash = "sha256:fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc"}, 215 | {file = "attrs-20.2.0.tar.gz", hash = "sha256:26b54ddbbb9ee1d34d5d3668dd37d6cf74990ab23c828c2888dccdceee395594"}, 216 | ] 217 | certifi = [ 218 | {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"}, 219 | {file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"}, 220 | ] 221 | chardet = [ 222 | {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, 223 | {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, 224 | ] 225 | click = [ 226 | {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, 227 | {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, 228 | ] 229 | fastapi = [ 230 | {file = "fastapi-0.61.1-py3-none-any.whl", hash = "sha256:6cc31bb555dd8ca956d1d227477d661e4ac012337242a41d36214ffbda78bfe9"}, 231 | {file = "fastapi-0.61.1.tar.gz", hash = "sha256:61ed73b4304413a2ea618d1b95ea866ee386e0e62dd8659c4f5059286f4a39c2"}, 232 | ] 233 | h11 = [ 234 | {file = "h11-0.11.0-py2.py3-none-any.whl", hash = "sha256:ab6c335e1b6ef34b205d5ca3e228c9299cc7218b049819ec84a388c2525e5d87"}, 235 | {file = "h11-0.11.0.tar.gz", hash = "sha256:3c6c61d69c6f13d41f1b80ab0322f1872702a3ba26e12aa864c928f6a43fbaab"}, 236 | ] 237 | idna = [ 238 | {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, 239 | {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, 240 | ] 241 | multidict = [ 242 | {file = "multidict-4.7.6-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:275ca32383bc5d1894b6975bb4ca6a7ff16ab76fa622967625baeebcf8079000"}, 243 | {file = "multidict-4.7.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:1ece5a3369835c20ed57adadc663400b5525904e53bae59ec854a5d36b39b21a"}, 244 | {file = "multidict-4.7.6-cp35-cp35m-win32.whl", hash = "sha256:5141c13374e6b25fe6bf092052ab55c0c03d21bd66c94a0e3ae371d3e4d865a5"}, 245 | {file = "multidict-4.7.6-cp35-cp35m-win_amd64.whl", hash = "sha256:9456e90649005ad40558f4cf51dbb842e32807df75146c6d940b6f5abb4a78f3"}, 246 | {file = "multidict-4.7.6-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:e0d072ae0f2a179c375f67e3da300b47e1a83293c554450b29c900e50afaae87"}, 247 | {file = "multidict-4.7.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:3750f2205b800aac4bb03b5ae48025a64e474d2c6cc79547988ba1d4122a09e2"}, 248 | {file = "multidict-4.7.6-cp36-cp36m-win32.whl", hash = "sha256:f07acae137b71af3bb548bd8da720956a3bc9f9a0b87733e0899226a2317aeb7"}, 249 | {file = "multidict-4.7.6-cp36-cp36m-win_amd64.whl", hash = "sha256:6513728873f4326999429a8b00fc7ceddb2509b01d5fd3f3be7881a257b8d463"}, 250 | {file = "multidict-4.7.6-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:feed85993dbdb1dbc29102f50bca65bdc68f2c0c8d352468c25b54874f23c39d"}, 251 | {file = "multidict-4.7.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fcfbb44c59af3f8ea984de67ec7c306f618a3ec771c2843804069917a8f2e255"}, 252 | {file = "multidict-4.7.6-cp37-cp37m-win32.whl", hash = "sha256:4538273208e7294b2659b1602490f4ed3ab1c8cf9dbdd817e0e9db8e64be2507"}, 253 | {file = "multidict-4.7.6-cp37-cp37m-win_amd64.whl", hash = "sha256:d14842362ed4cf63751648e7672f7174c9818459d169231d03c56e84daf90b7c"}, 254 | {file = "multidict-4.7.6-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:c026fe9a05130e44157b98fea3ab12969e5b60691a276150db9eda71710cd10b"}, 255 | {file = "multidict-4.7.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:51a4d210404ac61d32dada00a50ea7ba412e6ea945bbe992e4d7a595276d2ec7"}, 256 | {file = "multidict-4.7.6-cp38-cp38-win32.whl", hash = "sha256:5cf311a0f5ef80fe73e4f4c0f0998ec08f954a6ec72b746f3c179e37de1d210d"}, 257 | {file = "multidict-4.7.6-cp38-cp38-win_amd64.whl", hash = "sha256:7388d2ef3c55a8ba80da62ecfafa06a1c097c18032a501ffd4cabbc52d7f2b19"}, 258 | {file = "multidict-4.7.6.tar.gz", hash = "sha256:fbb77a75e529021e7c4a8d4e823d88ef4d23674a202be4f5addffc72cbb91430"}, 259 | ] 260 | pydantic = [ 261 | {file = "pydantic-1.6.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:418b84654b60e44c0cdd5384294b0e4bc1ebf42d6e873819424f3b78b8690614"}, 262 | {file = "pydantic-1.6.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:4900b8820b687c9a3ed753684337979574df20e6ebe4227381d04b3c3c628f99"}, 263 | {file = "pydantic-1.6.1-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:b49c86aecde15cde33835d5d6360e55f5e0067bb7143a8303bf03b872935c75b"}, 264 | {file = "pydantic-1.6.1-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:2de562a456c4ecdc80cf1a8c3e70c666625f7d02d89a6174ecf63754c734592e"}, 265 | {file = "pydantic-1.6.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f769141ab0abfadf3305d4fcf36660e5cf568a666dd3efab7c3d4782f70946b1"}, 266 | {file = "pydantic-1.6.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2dc946b07cf24bee4737ced0ae77e2ea6bc97489ba5a035b603bd1b40ad81f7e"}, 267 | {file = "pydantic-1.6.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:36dbf6f1be212ab37b5fda07667461a9219c956181aa5570a00edfb0acdfe4a1"}, 268 | {file = "pydantic-1.6.1-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:1783c1d927f9e1366e0e0609ae324039b2479a1a282a98ed6a6836c9ed02002c"}, 269 | {file = "pydantic-1.6.1-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:cf3933c98cb5e808b62fae509f74f209730b180b1e3c3954ee3f7949e083a7df"}, 270 | {file = "pydantic-1.6.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f8af9b840a9074e08c0e6dc93101de84ba95df89b267bf7151d74c553d66833b"}, 271 | {file = "pydantic-1.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:40d765fa2d31d5be8e29c1794657ad46f5ee583a565c83cea56630d3ae5878b9"}, 272 | {file = "pydantic-1.6.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:3fa799f3cfff3e5f536cbd389368fc96a44bb30308f258c94ee76b73bd60531d"}, 273 | {file = "pydantic-1.6.1-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:6c3f162ba175678218629f446a947e3356415b6b09122dcb364e58c442c645a7"}, 274 | {file = "pydantic-1.6.1-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:eb75dc1809875d5738df14b6566ccf9fd9c0bcde4f36b72870f318f16b9f5c20"}, 275 | {file = "pydantic-1.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:530d7222a2786a97bc59ee0e0ebbe23728f82974b1f1ad9a11cd966143410633"}, 276 | {file = "pydantic-1.6.1-py36.py37.py38-none-any.whl", hash = "sha256:b5b3489cb303d0f41ad4a7390cf606a5f2c7a94dcba20c051cd1c653694cb14d"}, 277 | {file = "pydantic-1.6.1.tar.gz", hash = "sha256:54122a8ed6b75fe1dd80797f8251ad2063ea348a03b77218d73ea9fe19bd4e73"}, 278 | ] 279 | requests = [ 280 | {file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"}, 281 | {file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"}, 282 | ] 283 | starlette = [ 284 | {file = "starlette-0.13.6-py3-none-any.whl", hash = "sha256:bd2ffe5e37fb75d014728511f8e68ebf2c80b0fa3d04ca1479f4dc752ae31ac9"}, 285 | {file = "starlette-0.13.6.tar.gz", hash = "sha256:ebe8ee08d9be96a3c9f31b2cb2a24dbdf845247b745664bd8a3f9bd0c977fdbc"}, 286 | ] 287 | urllib3 = [ 288 | {file = "urllib3-1.25.11-py2.py3-none-any.whl", hash = "sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e"}, 289 | {file = "urllib3-1.25.11.tar.gz", hash = "sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2"}, 290 | ] 291 | uvicorn = [ 292 | {file = "uvicorn-0.12.1-py3-none-any.whl", hash = "sha256:d06a25caa8dc680ad92eb3ec67363f5281c092059613a1cc0100acba37fc0f45"}, 293 | {file = "uvicorn-0.12.1.tar.gz", hash = "sha256:a461e76406088f448f36323f5ac774d50e5a552b6ccb54e4fca8d83ef614a7c2"}, 294 | ] 295 | yarl = [ 296 | {file = "yarl-1.5.1-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:db6db0f45d2c63ddb1a9d18d1b9b22f308e52c83638c26b422d520a815c4b3fb"}, 297 | {file = "yarl-1.5.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:17668ec6722b1b7a3a05cc0167659f6c95b436d25a36c2d52db0eca7d3f72593"}, 298 | {file = "yarl-1.5.1-cp35-cp35m-win32.whl", hash = "sha256:040b237f58ff7d800e6e0fd89c8439b841f777dd99b4a9cca04d6935564b9409"}, 299 | {file = "yarl-1.5.1-cp35-cp35m-win_amd64.whl", hash = "sha256:f18d68f2be6bf0e89f1521af2b1bb46e66ab0018faafa81d70f358153170a317"}, 300 | {file = "yarl-1.5.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:c52ce2883dc193824989a9b97a76ca86ecd1fa7955b14f87bf367a61b6232511"}, 301 | {file = "yarl-1.5.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ce584af5de8830d8701b8979b18fcf450cef9a382b1a3c8ef189bedc408faf1e"}, 302 | {file = "yarl-1.5.1-cp36-cp36m-win32.whl", hash = "sha256:df89642981b94e7db5596818499c4b2219028f2a528c9c37cc1de45bf2fd3a3f"}, 303 | {file = "yarl-1.5.1-cp36-cp36m-win_amd64.whl", hash = "sha256:3a584b28086bc93c888a6c2aa5c92ed1ae20932f078c46509a66dce9ea5533f2"}, 304 | {file = "yarl-1.5.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:da456eeec17fa8aa4594d9a9f27c0b1060b6a75f2419fe0c00609587b2695f4a"}, 305 | {file = "yarl-1.5.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bc2f976c0e918659f723401c4f834deb8a8e7798a71be4382e024bcc3f7e23a8"}, 306 | {file = "yarl-1.5.1-cp37-cp37m-win32.whl", hash = "sha256:4439be27e4eee76c7632c2427ca5e73703151b22cae23e64adb243a9c2f565d8"}, 307 | {file = "yarl-1.5.1-cp37-cp37m-win_amd64.whl", hash = "sha256:48e918b05850fffb070a496d2b5f97fc31d15d94ca33d3d08a4f86e26d4e7c5d"}, 308 | {file = "yarl-1.5.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:9b930776c0ae0c691776f4d2891ebc5362af86f152dd0da463a6614074cb1b02"}, 309 | {file = "yarl-1.5.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b3b9ad80f8b68519cc3372a6ca85ae02cc5a8807723ac366b53c0f089db19e4a"}, 310 | {file = "yarl-1.5.1-cp38-cp38-win32.whl", hash = "sha256:f379b7f83f23fe12823085cd6b906edc49df969eb99757f58ff382349a3303c6"}, 311 | {file = "yarl-1.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:9102b59e8337f9874638fcfc9ac3734a0cfadb100e47d55c20d0dc6087fb4692"}, 312 | {file = "yarl-1.5.1.tar.gz", hash = "sha256:c22c75b5f394f3d47105045ea551e08a3e804dc7e01b37800ca35b58f856c3d6"}, 313 | ] 314 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "async_intro" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["kingname "] 6 | 7 | [tool.poetry.dependencies] 8 | python = "^3.8" 9 | fastapi = "^0.61.1" 10 | aiohttp = "^3.6.3" 11 | uvicorn = "^0.12.1" 12 | urllib3 = "^1.25.10" 13 | requests = "^2.24.0" 14 | 15 | [tool.poetry.dev-dependencies] 16 | 17 | [build-system] 18 | requires = ["poetry>=0.12"] 19 | build-backend = "poetry.masonry.api" 20 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## 学完就能掌握的 Python asyncio 基础课 2 | 3 | 这是我的直播《学完就能掌握的 Python asyncio 基础课》的课件和源代码。视频回放地址:[学完就能掌握的 Python asyncio 基础课](https://www.bilibili.com/video/BV1Xq4y1D7Fs) 4 | 5 | 如果这个直播对立有帮助,请考虑关注我的微信公众号: 6 | 7 | ![](https://kingname-1257411235.cos.ap-chengdu.myqcloud.com/640.gif) 8 | -------------------------------------------------------------------------------- /server.py: -------------------------------------------------------------------------------- 1 | import time 2 | from fastapi import FastAPI 3 | 4 | 5 | app = FastAPI() 6 | 7 | 8 | @app.get('/') 9 | def index(): 10 | return {'success': True, 'msg': '请访问/sleep/{num}页面。'} 11 | 12 | 13 | @app.get('/sleep/{num}') 14 | def sleep(num: int): 15 | time.sleep(num) 16 | return {'success': True, 'msg': f'等待时间: {num}秒。'} -------------------------------------------------------------------------------- /test_class.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import httpx 3 | 4 | 5 | class Test: 6 | def __init__(self): 7 | self.name = 'kingname' 8 | 9 | async def req(self, url): 10 | async with httpx.AsyncClient() as client: 11 | resp = await client.get(url) 12 | result = resp.json() 13 | print(result) 14 | 15 | 16 | test = Test() 17 | asyncio.run(test.req('http://xxx')) -------------------------------------------------------------------------------- /一学就会的 Python asyncio 基础课.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingname/asyncio_intro/4322ce9efca2b403e52d563e32646a3ed88216e8/一学就会的 Python asyncio 基础课.pdf --------------------------------------------------------------------------------