Nhận dữ liệu từ chức năng async python

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àn

Mộ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

import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
7 hoặc một hàm được trang trí bằng
import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
8. Một trong các chức năng dưới đây sẽ hoạt động như một quy trình đăng quang và có hiệu quả tương đương về loại

import asyncio

async def ping_server[ip]:
    pass

@asyncio.coroutine
def load_file[path]:
    pass

Đâ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 hàm có phải là coroutine hay không, thì

import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
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

import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
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
import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
4 [mà chúng ta sẽ đề cập sau]

Biểu thức

import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
3 có thể được sử dụng như sau

import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']

Như bạn có thể thấy,

import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
3 đang được sử dụng trong một chức năng được trang trí bằng
import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
8. Nếu bạn thử và sử dụng
import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
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ố 8

Để 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ờ đợi

Cú pháp mới hơn và rõ ràng hơn là sử dụng các từ khóa

import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
4. Được giới thiệu trong Python 3. 5,
import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
7 đượ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í
import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
8 thực hiện. 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

  File "main.py", line 1
    file_content = yield from load_file['/Users/scott/data.txt']
                  ^
SyntaxError: 'yield' outside function
2, thay vì
import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
3, nhưng theo cách tương tự

import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
2

Một lần nữa, giống như

import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
3, bạn không thể sử dụng cái này bên ngoài một coroutine khác, nếu không bạn sẽ gặp lỗi cú pháp

Trong Trăn 3. 5, cả hai cách gọi coroutine đều được hỗ trợ, nhưng cách gọi

import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
4 được coi là cú pháp chính

Chạy vòng lặp sự kiện

Khô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

  • Đăng ký, thực hiện và hủy cuộc gọi bị trì hoãn [chức năng không đồng bộ]
  • Tạo vận chuyển máy khách và máy chủ để liên lạc
  • Tạo các quy trình con và vận chuyển để liên lạc với chương trình khác
  • Chức năng ủy quyền gọi đến một nhóm chủ đề

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

import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
5

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 [

  File "main.py", line 1
    file_content = yield from load_file['/Users/scott/data.txt']
                  ^
SyntaxError: 'yield' outside function
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ặp

Hàm

  File "main.py", line 1
    file_content = yield from load_file['/Users/scott/data.txt']
                  ^
SyntaxError: 'yield' outside function
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 ra

Bâ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ị,

  File "main.py", line 1
    file_content = yield from load_file['/Users/scott/data.txt']
                  ^
SyntaxError: 'yield' outside function
8, được gọi bởi
  File "main.py", line 1
    file_content = yield from load_file['/Users/scott/data.txt']
                  ^
SyntaxError: 'yield' outside function
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
  File "main.py", line 1
    file_content = yield from load_file['/Users/scott/data.txt']
                  ^
SyntaxError: 'yield' outside function
2, vòng lặp sự kiện sau đó 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ề
  File "main.py", line 1
    file_content = yield from load_file['/Users/scott/data.txt']
                  ^
SyntaxError: 'yield' outside function
9, được phân tích cú pháp và được in ra

import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
2

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

import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
22 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

import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
23, bạn có thể làm điều này với PIP

import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
5

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

import asyncio

@asyncio.coroutine
def get_json[client, url]:
    file_content = yield from load_file['/Users/scott/data.txt']
6

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ận

Mặ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?

Hàm async có thể trả về giá trị Python không?

Nó chỉ có thể được sử dụng bên trong các khối mã không đồng bộ [nghĩa là. trong khối mã của câu lệnh async def xác định hàm coroutine] và nó được sử dụng làm biểu thức nhận một tham số duy nhất và trả về một giá trị .

Làm thế nào để async hoạt động trong Python?

Async IO mất nhiều thời gian chờ đợi, trong đó các chức năng sẽ bị chặn và cho phép các chức năng khác chạy trong thời gian ngừng hoạt động đó . [Một chức năng chặn hiệu quả cấm những người khác chạy từ khi nó bắt đầu cho đến khi nó quay trở lại. ]

Làm cách nào để sử dụng asyncio trong Python?

Asyncio là một thư viện Python được sử dụng để chạy mã đồng thời bằng lệnh async/wait. .
nhập asyncio
async def main[]
print["Chờ 5 giây. "]
cho _ trong phạm vi[5]
chờ đợi không đồng bộ. ngủ[1]
in ["Xin chào"]
print["Xong đợi. "]
không đồng bộ. chạy [chính[]]

Python không đồng bộ hay đồng bộ?

Có hai loại phương thức cơ bản trong Parallels Python API. đồng bộ và không đồng bộ . Khi một phương thức đồng bộ được gọi, nó sẽ hoàn thành việc thực thi trước khi quay lại trình gọi. Một phương thức không đồng bộ bắt đầu một công việc ở chế độ nền và trả lại cho người gọi ngay lập tức.

Chủ Đề