Gọi hàm async từ python chính
Với lập trình bất đồng bộ, chúng ta có thể thực thi các tác vụ đồng thời với việc thực thi chương trình chính. Các từ khóa không đồng bộ và chờ đợi đơn giản hóa việc lập trình không đồng bộ trong Python. Python có mô hình lập trình không đồng bộ được tích hợp trong ngôn ngữ Show
Coroutine là một chức năng Python được sử dụng trong đa nhiệm hợp tác, nơi chúng có thể bị tạm dừng và tiếp tục. Một coroutine được khai báo với cú pháp async def mul(x, y): return x * y0 Các từ khóa async/awaitCác từ khóa async def mul(x, y): return x * y1 đã được chuẩn hóa trong Python 3. 7. Họ đơn giản hóa lập trình không đồng bộ trong Python. Từ khóa async def mul(x, y): return x * y2 được sử dụng để tạo quy trình đăng ký Python. Từ khóa async def mul(x, y): return x * y3 tạm dừng thực thi quy trình đăng ký cho đến khi nó hoàn thành và trả về dữ liệu kết quả. Các từ khóa chờ đợi chỉ hoạt động trong chức năng không đồng bộ Sau đây là một chương trình đơn giản sử dụng từ khóa async def mul(x, y): return x * y1 #!/usr/bin/python import asyncio async def mul(x, y): return x * y loop = asyncio.get_event_loop() res = loop.run_until_complete(mul(5, 5)) print(res2) loop.close() Chương trình tạo và chạy một chức năng không đồng bộ async def mul(x, y): return x * y Một coroutine là một hàm được khai báo với công cụ sửa đổi async def mul(x, y): return x * y2________số 8_______ async def mul(x, y): return x * y6 trả về vòng lặp sự kiện asyncio. Cần có một vòng lặp sự kiện để thực thi mã không đồng bộ res = loop.run_until_complete(mul(5, 5)) Hàm async def mul(x, y): return x * y7 chạy vòng lặp sự kiện cho đến khi hoàn thành một tương lai. Nó trả về kết quả của tương lai hoặc tăng ngoại lệ của nó. Tương lai đại diện cho kết quả cuối cùng của hoạt động không đồng bộ Python async/await ví dụ IIVới async def mul(x, y): return x * y8, chúng tôi đơn giản hóa mã. Hàm tạo một vòng lặp sự kiện, lên lịch cho các coroutines và cuối cùng đóng vòng lặp #!/usr/bin/python import asyncio async def add(x, y): return x + y async def get_results(): res1 = await add(3, 4) res2 = await add(8, 5) print(res1, res2) asyncio.run(get_results()) Trong ví dụ, chúng tôi chạy hai hàm async $ python simple2.py 7 13 Thu thập là một cách thuận tiện để lên lịch cho nhiều coroutine chạy đồng thời. Chúng tôi thu thập các coroutines với async def mul(x, y): return x * y9 Với loop = asyncio.get_event_loop()0, chúng tôi tạo một coroutine hoàn thành trong số giây đã chỉ định. Nó thường được sử dụng để mô phỏng một nhiệm vụ chạy dài #!/usr/bin/python import asyncio import time import random async def task1(): wait = random.randint(0, 3) await asyncio.sleep(wait) print("task 1 finished") async def task2(): wait = random.randint(0, 3) await asyncio.sleep(wait) print("task 2 finished") async def task3(): wait = random.randint(0, 3) await asyncio.sleep(wait) print("task 3 finished") async def main(): for x in range(2): await asyncio.gather(task1(), task2(), task3()) time.sleep(1) print('----------------------------') t1 = time.perf_counter() asyncio.run(main()) t2 = time.perf_counter() print(f'Total time elapsed: {t2-t1:0.2f} seconds') Chúng tôi có ba nhiệm vụ hoàn thành trong một số giây ngẫu nhiên. Bằng cách này, chúng tôi mô phỏng việc thực hiện ba tác vụ dài hạn khác nhau async def main(): for x in range(2): await asyncio.gather(task1(), task2(), task3()) print('----------------------------') Các chức năng chính tập hợp tất cả ba nhiệm vụ. Nó cũng là một coroutine, được trang trí bằng async def mul(x, y): return x * y2. Chúng tôi đang chờ kết quả của async def mul(x, y): return x * y9 với từ khóa async def mul(x, y): return x * y3 $ python simple3.py task 2 finished task 1 finished task 3 finished ---------------------------- task 3 finished task 2 finished task 1 finished ---------------------------- Total time elapsed: 8.01 seconds Ví dụ không đồng bộ Python PlaywrightNhiều thư viện có hỗ trợ lập trình không đồng bộ. Thư viện MS Playwright cho phép tự động hóa các trình duyệt ở cả chế độ đồng bộ và không đồng bộ Lập trình không đồng bộ đã đạt được rất nhiều sức hút trong vài năm qua và vì lý do chính đáng. Mặc dù nó có thể khó hơn kiểu tuyến tính truyền thống, nhưng nó cũng hiệu quả hơn nhiều Ví dụ: thay vì đợi một yêu cầu HTTP kết thúc trước khi tiếp tục thực hiện, với các coroutine không đồng bộ của Python, bạn có thể gửi yêu cầu và thực hiện các công việc khác đang chờ trong hàng đợi trong khi chờ yêu cầu HTTP kết thúc. Có thể cần suy nghĩ thêm một chút để hiểu đúng logic, nhưng bạn sẽ có thể xử lý nhiều công việc hơn với ít tài nguyên hơn Ngay cả khi đó, cú pháp và việc thực thi các hàm không đồng bộ trong các ngôn ngữ như Python thực sự không khó lắm. Bây giờ, JavaScript là một câu chuyện khác, nhưng Python dường như thực thi nó khá tốt Tính không đồng bộ dường như là một lý do lớn tại sao Node. js rất phổ biến cho lập trình phía máy chủ. Phần lớn mã chúng tôi viết, đặc biệt là trong các ứng dụng IO nặng như trang web, phụ thuộc vào tài nguyên bên ngoài. Đây có thể là bất cứ thứ gì từ cuộc gọi cơ sở dữ liệu từ xa đến POST tới dịch vụ REST. Ngay khi bạn yêu cầu bất kỳ tài nguyên nào trong số này, mã của bạn sẽ chờ xung quanh mà không có gì để làm Với lập trình không đồng bộ, bạn cho phép mã của mình xử lý các tác vụ khác trong khi chờ các tài nguyên khác này phản hồi quân đoànMột hàm không đồng bộ trong Python thường được gọi là 'coroutine', đây chỉ là một hàm sử dụng từ khóa
Đây là những hàm đặc biệt trả về các đối tượng coroutine khi được gọi. Nếu bạn đã quen thuộc với JavaScript Promises, thì bạn có thể coi đối tượng được trả về này gần giống như một Promise. Gọi một trong hai điều này không thực sự chạy chúng, mà thay vào đó, một đối tượng được trả về, sau đó có thể được chuyển đến vòng lặp sự kiện để được thực thi sau này Trong trường hợp bạn cần xác định xem một chức năng có phải là một coroutine hay không, thì 0 sẽ cung cấp phương thức thực hiện chính xác điều này cho bạn. Hoặc, nếu bạn cần xác định xem một đối tượng được trả về từ một hàm có phải là một đối tượng coroutine hay không, bạn có thể sử dụng thay thếNăng suất từCó một vài cách để thực sự gọi một coroutine, một trong số đó là phương thức 3. Điều này đã được giới thiệu trong Python 3. 3 và đã được cải thiện hơn nữa trong Python 3. 5 ở dạng 4 (chúng ta sẽ đề cập sau)Biểu thức 3 có thể được sử dụng như sau
Như bạn có thể thấy, 3 đang được sử dụng trong một chức năng được trang trí bằng @asyncio.coroutine . Nếu bạn thử và sử dụng 3 bên ngoài chức năng này, thì bạn sẽ gặp lỗi từ Python như thế này
Để sử dụng cú pháp này, nó phải nằm trong một hàm khác (thường là với trình trang trí coroutine) Không đồng bộ/chờ đợiCú pháp mới hơn và rõ ràng hơn là sử dụng các từ khóa 4. Được giới thiệu trong Python 3. 5, async được sử dụng để khai báo một chức năng như một coroutine, giống như những gì mà trình trang trí @asyncio.coroutine làm. Nó có thể được áp dụng cho hàm bằng cách đặt nó ở phía trước của định nghĩaĐể thực sự gọi hàm này, chúng tôi sử dụng 2, thay vì 3, nhưng theo cách tương tự
Một lần nữa, giống như 3, bạn không thể sử dụng this bên ngoài một coroutine khác, nếu không bạn sẽ gặp lỗi cú phápTrong Trăn 3. 5, cả hai cách gọi coroutine đều được hỗ trợ, nhưng cách 4 được coi là cú pháp chínhChạy vòng lặp sự kiệnKhông có nội dung coroutine nào tôi mô tả ở trên sẽ quan trọng (hoặc hoạt động) nếu bạn không biết cách bắt đầu và chạy một vòng lặp sự kiện. Vòng lặp sự kiện là điểm thực thi trung tâm cho các chức năng không đồng bộ, vì vậy khi bạn thực sự muốn thực thi coroutine, đây là thứ bạn sẽ sử dụng Vòng lặp sự kiện cung cấp khá nhiều tính năng cho bạn
Hãy xem hướng dẫn thực hành, thực tế của chúng tôi để học Git, với các phương pháp hay nhất, tiêu chuẩn được ngành chấp nhận và bao gồm bảng gian lận. Dừng các lệnh Git trên Google và thực sự tìm hiểu nó Mặc dù thực tế có khá nhiều cấu hình và loại vòng lặp sự kiện mà bạn có thể sử dụng, nhưng hầu hết các chương trình bạn viết sẽ chỉ cần sử dụng thứ gì đó như thế này để lên lịch cho một chức năng
Ba dòng cuối cùng là những gì chúng tôi quan tâm ở đây. Nó bắt đầu bằng cách nhận vòng lặp sự kiện mặc định ( 6), lên lịch và chạy tác vụ không đồng bộ, sau đó đóng vòng lặp khi chạy xong vòng lặpHàm 7 thực sự đang chặn, vì vậy nó sẽ không trả về cho đến khi tất cả các phương thức không đồng bộ được thực hiện. Vì chúng tôi chỉ chạy cái này trên một luồng, nên không có cách nào nó có thể di chuyển về phía trước trong khi vòng lặp đang diễn raBây giờ, bạn có thể nghĩ rằng điều này không hữu ích lắm vì dù sao chúng ta cũng chặn vòng lặp sự kiện (thay vì chỉ các lệnh gọi IO), nhưng hãy tưởng tượng gói toàn bộ chương trình của bạn trong một hàm không đồng bộ, sau đó sẽ cho phép bạn chạy nhiều lệnh không đồng bộ Bạn thậm chí có thể ngắt vòng lặp sự kiện thành luồng riêng của nó, cho phép nó xử lý tất cả các yêu cầu IO dài trong khi luồng chính xử lý logic chương trình hoặc giao diện người dùng Một ví dụĐược rồi, vậy hãy xem một ví dụ lớn hơn một chút mà chúng ta thực sự có thể chạy. Đoạn mã sau là một chương trình không đồng bộ khá đơn giản, lấy JSON từ Reddit, phân tích cú pháp JSON và in ra các bài đăng hàng đầu trong ngày từ /r/python, /r/programming và /r/compsci Phương thức đầu tiên được hiển thị, 8, được gọi bởi 9 và chỉ tạo một yêu cầu HTTP GET tới URL Reddit thích hợp. Khi điều này được gọi với 2, thì vòng lặp sự kiện có thể tiếp tục và phục vụ các coroutine khác trong khi chờ phản hồi HTTP quay lại. Sau khi thực hiện xong, JSON được trả về 9, được phân tích cú pháp và được in ra
Mã này hơi khác so với mã mẫu mà chúng tôi đã trình bày trước đó. Để có nhiều coroutine chạy trên vòng lặp sự kiện, chúng tôi đang sử dụng 2 và sau đó chạy vòng lặp mãi mãi để xử lý mọi thứĐể chạy cái này, trước tiên bạn cần cài đặt 3, bạn có thể làm điều này với PIP
Bây giờ chỉ cần chắc chắn rằng bạn chạy nó với Python 3. 5 trở lên, và bạn sẽ nhận được kết quả như thế này
Lưu ý rằng nếu bạn chạy điều này một vài lần, thứ tự in dữ liệu subreddit sẽ thay đổi. Điều này là do mỗi lệnh gọi chúng tôi thực hiện kiểm soát (lợi nhuận) của luồng, cho phép một lệnh gọi HTTP khác xử lý. Cái nào về trước in ra trước Phần kết luậnMặc dù chức năng không đồng bộ tích hợp sẵn của Python không mượt mà như JavaScript, nhưng điều đó không có nghĩa là bạn không thể sử dụng nó cho các ứng dụng thú vị và hiệu quả. Chỉ cần dành 30 phút để tìm hiểu thông tin chi tiết và bạn sẽ hiểu rõ hơn nhiều về cách bạn có thể tích hợp điều này vào các ứng dụng của riêng mình Bạn nghĩ gì về async/await của Python? Làm cách nào để gọi Python chính không đồng bộ?Trong asyncio Coroutine có thể được tạo bằng cách sử dụng từ khóa async trước def. Để chạy chức năng không đồng bộ (coroutine), bạn phải gọi nó bằng Vòng lặp sự kiện . Vòng lặp sự kiện. Bạn có thể coi Vòng lặp sự kiện là các chức năng để chạy các tác vụ và lệnh gọi lại không đồng bộ, thực hiện các hoạt động IO mạng và chạy các quy trình con.
Bạn có thể gọi một chức năng không đồng bộ không?Các khai báo hàm không đồng bộ được nâng lên đầu phạm vi của chúng và có thể được gọi ở bất kỳ đâu trong phạm vi của chúng .
Bạn có thể gọi một hàm async mà không cần chờ Python không?Không thể , vì kết quả đó không tồn tại. Gọi hàm async không tạo chuỗi, nó tạo một máy trạng thái sẽ tạo chuỗi khi được thăm dò. . await đang thực sự chạy mã.
Python có thể chạy không đồng bộ không?asyncio được sử dụng làm nền tảng cho nhiều khung không đồng bộ Python cung cấp mạng hiệu suất cao và máy chủ web, thư viện kết nối cơ sở dữ liệu, hàng đợi tác vụ phân tán, v.v. asyncio thường phù hợp hoàn hảo với mã mạng có cấu trúc cấp cao và ràng buộc IO. |