{"id":740,"date":"2026-03-19T12:22:00","date_gmt":"2026-03-19T04:22:00","guid":{"rendered":"https:\/\/mitongxue.cn\/?p=740"},"modified":"2026-07-21T13:33:00","modified_gmt":"2026-07-21T05:33:00","slug":"python%e5%b8%b8%e7%94%a8%e5%bc%82%e6%ad%a5%e7%bc%96%e7%a8%8b%e6%a8%a1%e5%bc%8f","status":"publish","type":"post","link":"https:\/\/mitongxue.cn\/index.php\/2026\/03\/19\/python%e5%b8%b8%e7%94%a8%e5%bc%82%e6%ad%a5%e7%bc%96%e7%a8%8b%e6%a8%a1%e5%bc%8f\/","title":{"rendered":"python\u5e38\u7528\u5f02\u6b65\u7f16\u7a0b\u6a21\u5f0f"},"content":{"rendered":"\n<h3 class=\"wp-block-heading\">\u5e76\u53d1\u6279\u5904\u7406\u6a21\u5f0f<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>async def batch_process(urls: list&#91;str]):<br> &nbsp; &nbsp;\"\"\"\u5c06\u4e00\u6279\u4efb\u52a1\u5e76\u53d1\u6267\u884c\uff0c\u5e76\u6536\u96c6\u7ed3\u679c\"\"\"<br> &nbsp; &nbsp;async def process(url: str) -&gt; dict:<br> &nbsp; &nbsp; &nbsp; &nbsp;async with httpx.AsyncClient() as client:<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;resp = await client.get(url)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return {\"url\": url, \"status\": resp.status_code}<br>\u200b<br> &nbsp; &nbsp;results = await asyncio.gather(*&#91;process(url) for url in urls])<br> &nbsp; &nbsp;return results<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\u9650\u901f\u5668\u6a21\u5f0f<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>class RateLimiter:<br> &nbsp; &nbsp;\"\"\"\u9650\u5236\u5355\u4f4d\u65f6\u95f4\u5185\u7684\u8bf7\u6c42\u6570\"\"\"<br>\u200b<br> &nbsp; &nbsp;def __init__(self, max_rate: float, interval: float = 1.0):<br> &nbsp; &nbsp; &nbsp; &nbsp;self._sem = asyncio.Semaphore(max_rate)<br> &nbsp; &nbsp; &nbsp; &nbsp;self._interval = interval<br>\u200b<br> &nbsp; &nbsp;async def acquire(self):<br> &nbsp; &nbsp; &nbsp; &nbsp;await self._sem.acquire()<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;def release():<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;self._sem.release()<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;loop = asyncio.get_running_loop()<br> &nbsp; &nbsp; &nbsp; &nbsp;loop.call_later(self._interval, release)<br>\u200b<br> &nbsp; &nbsp;async def __aenter__(self):<br> &nbsp; &nbsp; &nbsp; &nbsp;await self.acquire()<br>\u200b<br> &nbsp; &nbsp;async def __aexit__(self, *args):<br> &nbsp; &nbsp; &nbsp; &nbsp;pass<br>\u200b<br>\u200b<br>async def main():<br> &nbsp; &nbsp;rate_limiter = RateLimiter(max_rate=2, interval=1.0)<br>\u200b<br> &nbsp; &nbsp;async def fetch(url: str) -&gt; str:<br> &nbsp; &nbsp; &nbsp; &nbsp;async with rate_limiter:<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;await asyncio.sleep(0.3)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return f\"{url} done\"<br>\u200b<br> &nbsp; &nbsp;results = await asyncio.gather(*&#91;fetch(f\"url{i}\") for i in range(6)])<br> &nbsp; &nbsp;print(results) &nbsp;# \u6bcf\u79d2\u6700\u591a\u5b8c\u6210 2 \u4e2a\u8bf7\u6c42<br>\u200b<br>\u200b<br>asyncio.run(main())<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\u91cd\u8bd5\u6a21\u5f0f<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>async def retry(coro_factory, max_retries: int = 3, delay: float = 1.0):<br> &nbsp; &nbsp;\"\"\"\u4e3a\u5f02\u6b65\u64cd\u4f5c\u6dfb\u52a0\u91cd\u8bd5\u673a\u5236\"\"\"<br> &nbsp; &nbsp;for attempt in range(max_retries):<br> &nbsp; &nbsp; &nbsp; &nbsp;try:<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return await coro_factory()<br> &nbsp; &nbsp; &nbsp; &nbsp;except Exception as e:<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if attempt == max_retries - 1:<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;raise<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;print(f\"\u7b2c {attempt + 1} \u6b21\u5931\u8d25\uff0c{delay} \u79d2\u540e\u91cd\u8bd5...\")<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;await asyncio.sleep(delay)<br>\u200b<br>\u200b<br>async def main():<br> &nbsp; &nbsp;n = 0<br>\u200b<br> &nbsp; &nbsp;async def unstable_request() -&gt; str:<br> &nbsp; &nbsp; &nbsp; &nbsp;nonlocal n<br> &nbsp; &nbsp; &nbsp; &nbsp;n += 1<br> &nbsp; &nbsp; &nbsp; &nbsp;if n &lt; 3:<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;raise ConnectionError(f\"\u7b2c {n} \u6b21\u8bf7\u6c42\u5931\u8d25\")<br> &nbsp; &nbsp; &nbsp; &nbsp;return \"\u6210\u529f\u54cd\u5e94\"<br>\u200b<br> &nbsp; &nbsp;result = await retry(unstable_request, max_retries=3, delay=0.5)<br> &nbsp; &nbsp;print(result) &nbsp;# \u524d 2 \u6b21\u5931\u8d25\uff0c\u7b2c 3 \u6b21\u6210\u529f<br>\u200b<br>\u200b<br>asyncio.run(main())<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\u4f18\u96c5\u5173\u95ed\u6a21\u5f0f<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>import asyncio<br>import signal<br>\u200b<br>\u200b<br>class GracefulServer:<br> &nbsp; &nbsp;def __init__(self):<br> &nbsp; &nbsp; &nbsp; &nbsp;self._running = True<br>\u200b<br> &nbsp; &nbsp;async def serve(self):<br> &nbsp; &nbsp; &nbsp; &nbsp;while self._running:<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;try:<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;await asyncio.sleep(1) &nbsp;# \u6a21\u62df\u5904\u7406\u8bf7\u6c42<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;print(\"\u6b63\u5728\u5904\u7406\u8bf7\u6c42...\")<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;except asyncio.CancelledError:<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;print(\"\u6536\u5230\u53d6\u6d88\u4fe1\u53f7\uff0c\u6b63\u5728\u5173\u95ed...\")<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break<br>\u200b<br> &nbsp; &nbsp;def shutdown(self):<br> &nbsp; &nbsp; &nbsp; &nbsp;print(\"\u5f00\u59cb\u4f18\u96c5\u5173\u95ed...\")<br> &nbsp; &nbsp; &nbsp; &nbsp;self._running = False<br>\u200b<br> &nbsp; &nbsp;async def run(self):<br> &nbsp; &nbsp; &nbsp; &nbsp;loop = asyncio.get_running_loop()<br> &nbsp; &nbsp; &nbsp; &nbsp;stop = loop.create_future()<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;def signal_handler():<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;stop.set_result(None)<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;loop.add_signal_handler(signal.SIGINT, signal_handler) &nbsp;# Ctrl+C<br> &nbsp; &nbsp; &nbsp; &nbsp;loop.add_signal_handler(signal.SIGTERM, signal_handler) &nbsp;# \u7ec8\u6b62\u4fe1\u53f7<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;task = asyncio.create_task(self.serve())<br> &nbsp; &nbsp; &nbsp; &nbsp;await stop &nbsp;# \u7b49\u5f85\u5173\u95ed\u4fe1\u53f7<br> &nbsp; &nbsp; &nbsp; &nbsp;self.shutdown()<br> &nbsp; &nbsp; &nbsp; &nbsp;task.cancel()<br> &nbsp; &nbsp; &nbsp; &nbsp;await task<br>\u200b<br>\u200b<br>async def main():<br> &nbsp; &nbsp;server = GracefulServer()<br> &nbsp; &nbsp;await server.run()<br>\u200b<br>\u200b<br># \u6309 Ctrl+C \u89e6\u53d1 SIGINT\uff0c\u7a0b\u5e8f\u4f1a\u4f18\u96c5\u9000\u51fa\u800c\u975e\u76f4\u63a5\u5d29\u6e83<br>asyncio.run(main())<br>\u200b<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u5e76\u53d1\u6279\u5904\u7406\u6a21\u5f0f \u9650\u901f\u5668\u6a21\u5f0f \u91cd\u8bd5\u6a21\u5f0f \u4f18\u96c5\u5173\u95ed\u6a21\u5f0f<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[52,14],"tags":[],"class_list":["post-740","post","type-post","status-publish","format-standard","hentry","category-python","category-back"],"featured_image_urls":{"full":"","thumbnail":"","medium":"","medium_large":"","large":"","1536x1536":"","2048x2048":""},"author_info":{"info":["\u9648 \u67d0\u4eba"]},"category_info":"<a href=\"https:\/\/mitongxue.cn\/index.php\/category\/back\/python\/\" rel=\"category tag\">Python<\/a> <a href=\"https:\/\/mitongxue.cn\/index.php\/category\/back\/\" rel=\"category tag\">\u540e\u7aef<\/a>","tag_info":"\u540e\u7aef","comment_count":"0","_links":{"self":[{"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/posts\/740","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/comments?post=740"}],"version-history":[{"count":1,"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/posts\/740\/revisions"}],"predecessor-version":[{"id":741,"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/posts\/740\/revisions\/741"}],"wp:attachment":[{"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/media?parent=740"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/categories?post=740"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mitongxue.cn\/index.php\/wp-json\/wp\/v2\/tags?post=740"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}