demo_contextmanager.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. # class ResourceManager:
  2. # def __enter__(self):
  3. # print("1. 管家:已进入房间,空调已打开")
  4. # return "这是一把房间钥匙" # 返回给 with 后面的 as 变量
  5. #
  6. # def __exit__(self, exc_type, exc_val, exc_tb):
  7. # # print(f"exc_type-->{exc_type}")
  8. # # print(f"exc_val-->{exc_val}")
  9. # print("2. 管家:正在退出,垃圾已带走,空调已关闭")
  10. # # 返回 True 表示吞掉异常,返回 False 表示向外抛出异常
  11. #
  12. #
  13. # # 测试运行
  14. # with ResourceManager() as key:
  15. # # 即使这里报错,管家也会先执行关门再报错
  16. # # raise ValueError("不小心打碎杯子")
  17. # print(f"3. 我在房间里干活,拿着 {key}")
  18. # 输出顺序:1 -> 3 -> 2
  19. # from contextlib import contextmanager
  20. #
  21. # @contextmanager
  22. # def ResourceManager():
  23. # print("1. 开门,开空调")
  24. # try:
  25. # yield "钥匙" # 分界线,相当于 __enter__ 的返回值
  26. # finally:
  27. # # finally 保证即使报错也会执行关门
  28. # print("2. 关门,关空调,清理垃圾")
  29. #
  30. # # 使用
  31. # with ResourceManager() as key:
  32. # print(f"3. 干活中,拿着 {key}")
  33. # # 输出:1 -> 3 -> 2
  34. import asyncio
  35. #
  36. # class AsyncDatabaseConnection:
  37. # async def __aenter__(self): # 注意是 async def
  38. # print("1. [异步] 正在等待网络握手...")
  39. # await asyncio.sleep(1) # 模拟异步 IO 等待
  40. # print("2. [异步] 数据库连接成功")
  41. # return "连接对象"
  42. #
  43. # async def __aexit__(self, exc_type, exc_val, exc_tb):
  44. # print("3. [异步] 正在异步关闭连接,释放资源...")
  45. # await asyncio.sleep(0.5) # 模拟异步关闭等待
  46. # print("4. [异步] 连接已关闭")
  47. #
  48. #
  49. # # 使用(必须放在异步函数中)
  50. # async def main():
  51. # async with AsyncDatabaseConnection() as conn:
  52. # print(f"5. 正在执行 SQL 查询,使用 {conn}")
  53. # # 即使这里报错,上面的 aexit 依然会等待执行完毕
  54. #
  55. #
  56. # # 运行
  57. # asyncio.run(main())
  58. import asyncio
  59. from contextlib import asynccontextmanager
  60. @asynccontextmanager
  61. async def AsyncDatabaseConnection():
  62. print("1. [异步] 正在连接远程服务器...")
  63. await asyncio.sleep(1) # 开门需要等待
  64. try:
  65. yield "远程数据通道" # 返回给 as 变量
  66. finally:
  67. print("2. [异步] 正在断开连接,清理缓存...")
  68. await asyncio.sleep(0.5) # 关门也需要等待
  69. print("3. [异步] 已清理完毕")
  70. async def main():
  71. async with AsyncDatabaseConnection() as chanl:
  72. print(f"4. 正在传输数据,使用 {chanl}")
  73. # 即使报错,finally 块依然会等关门执行完
  74. asyncio.run(main())