Helpex - Trao đổi & giúp đỡ Đăng nhập

Giới thiệu về aiohttp

Python 3.5 đã thêm một số cú pháp mới cho phép các nhà phát triển tạo các gói và ứng dụng không đồng bộ dễ dàng hơn. Một gói như vậy là aiohttp là máy khách / máy chủ HTTP cho asyncio. Về cơ bản, nó cho phép bạn viết các máy khách và máy chủ không đồng bộ. Gói aiohttp cũng hỗ trợ Server WebSockets và Client WebSockets. Bạn có thể cài đặt aiohttp bằng pip:

pip install aiohttp

Bây giờ chúng ta đã cài đặt aiohttp, hãy xem một trong những ví dụ của họ!

Tìm nạp một trang web

Tài liệu về aiohtpp có một ví dụ thú vị cho thấy cách lấy HTML của trang web. Chúng ta hãy xem nó và xem nó hoạt động như thế nào:

import aiohttp
import asyncio
import async_timeout

async def fetch(session, url):
    with async_timeout.timeout(10):
        async with session.get(url) as response:
            return await response.text()

async def main(loop):
    async with aiohttp.ClientSession(loop=loop) as session:
        html = await fetch(session, 'http://www.blog.pythonlibrary.org')
        print(html)

loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))

Ở đây chúng ta chỉ cần nhập aiohttp, Python's asyncio và async_timeout, cho chúng ta khả năng hết thời gian của một coroutine. Chúng ta tạo vòng lặp sự kiện ở dưới cùng của mã và gọi hàm main (). Nó sẽ tạo một đối tượng ClientSession mà chúng ta chuyển đến hàm fetch () cùng với URL nào để tìm nạp. Cuối cùng, trong hàm fetch (), chúng tôi sử dụng đặt thời gian chờ và cố gắng lấy HTML của URL. Nếu mọi thứ hoạt động mà không có thời gian, bạn sẽ thấy một loạt các văn bản được đưa vào thiết bị xuất chuẩn.

Tải tập tin với aiohttp

Một tác vụ khá phổ biến mà các nhà phát triển sẽ làm là tải xuống các tệp bằng cách sử dụng các luồng hoặc các quy trình. Chúng tôi cũng có thể tải tập tin bằng coroutines! Hãy cùng tìm hiểu xem:

import aiohttp
import asyncio
import async_timeout
import os


async def download_coroutine(session, url):
    with async_timeout.timeout(10):
        async with session.get(url) as response:
            filename = os.path.basename(url)
            with open(filename, 'wb') as f_handle:
                while True:
                    chunk = await response.content.read(1024)
                    if not chunk:
                        break
                    f_handle.write(chunk)
            return await response.release()


async def main(loop):
    urls = ["http://www.irs.gov/pub/irs-pdf/f1040.pdf",
        "http://www.irs.gov/pub/irs-pdf/f1040a.pdf",
        "http://www.irs.gov/pub/irs-pdf/f1040ez.pdf",
        "http://www.irs.gov/pub/irs-pdf/f1040es.pdf",
        "http://www.irs.gov/pub/irs-pdf/f1040sb.pdf"]

    async with aiohttp.ClientSession(loop=loop) as session:
        for url in urls:
            await download_coroutine(session, url)


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(loop))

Bạn sẽ nhận thấy ở đây rằng chúng tôi nhập một vài mục mới: aiohttpasync_timeout . Cái sau thực sự là một trong những phụ thuộc của aiohttp và cho phép chúng ta tạo một trình quản lý bối cảnh hết thời gian chờ. Hãy bắt đầu ở dưới cùng của mã và làm việc theo cách của chúng tôi. Trong câu lệnh điều kiện dưới cùng, chúng ta bắt đầu vòng lặp sự kiện không đồng bộ và gọi hàm chính của chúng ta. Trong hàm chính, chúng tôi tạo một đối tượng ClientSession mà chúng tôi chuyển sang hàm coroutine tải xuống cho mỗi url chúng tôi muốn tải xuống. Trong download_coroutine , chúng tôi gọi phương thức get () của phiên cung cấp cho chúng tôi một đối tượng phản hồi. Bây giờ chúng ta đến phần có một chút ma thuật. Khi bạn sử dụng nội dungthuộc tính của đối tượng phản hồi, nó trả về một thể hiện của aiohttp.StreamReader cho phép chúng ta tải xuống tệp theo từng khối với bất kỳ kích thước nào chúng ta muốn. Khi chúng ta đọc tệp, chúng ta ghi nó ra đĩa cục bộ. Cuối cùng, chúng ta gọi phương thức release () của phản hồi , sẽ kết thúc quá trình xử lý phản hồi.

Theo tài liệu của aiohttp, vì đối tượng phản hồi được tạo trong trình quản lý ngữ cảnh, nên về mặt kỹ thuật, nó gọi là phát hành (). Nhưng trong Python, rõ ràng thường tốt hơn và có một lưu ý trong tài liệu rằng chúng ta không nên dựa vào kết nối sẽ biến mất, vì vậy tôi tin rằng tốt hơn là chỉ phát hành nó trong trường hợp này.

Có một phần vẫn đang bị chặn ở đây và đó là phần mã thực sự ghi vào đĩa. Trong khi chúng tôi đang viết tệp, chúng tôi vẫn đang chặn. Có một thư viện khác gọi là aiofiles mà chúng ta có thể sử dụng để thử và làm cho tệp viết không đồng bộ quá. Chúng ta sẽ xem xét tiếp theo.

Lưu ý: Phần trên cam từ một trong những bài viết trước của tôi .

Sử dụng aiofiles để viết không đồng bộ

Bạn sẽ cần phải cài đặt aiofiles để thực hiện công việc này. Hãy giải quyết nó theo cách đó:

pip install aiofiles

Bây giờ chúng tôi có tất cả các mục chúng tôi cần, chúng tôi có thể cập nhật mã của chúng tôi!

import aiofiles
import aiohttp
import asyncio
import async_timeout
import os
 
 
async def download_coroutine(session, url):
    with async_timeout.timeout(10):
        async with session.get(url) as response:
            filename = os.path.basename(url)
            async with aiofiles.open(filename, 'wb') as fd:
                while True:
                    chunk = await response.content.read(1024)
                    if not chunk:
                        break
                    await fd.write(chunk)
            return await response.release()
 
 
async def main(loop):
    urls = ["http://www.irs.gov/pub/irs-pdf/f1040.pdf",
        "http://www.irs.gov/pub/irs-pdf/f1040a.pdf",
        "http://www.irs.gov/pub/irs-pdf/f1040ez.pdf",
        "http://www.irs.gov/pub/irs-pdf/f1040es.pdf",
        "http://www.irs.gov/pub/irs-pdf/f1040sb.pdf"]
 
    async with aiohttp.ClientSession(loop=loop) as session:
        for url in urls:
            await download_coroutine(session, url)
 
 
if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(loop))

Thay đổi duy nhất là thêm một lần nhập cho aiofiles và sau đó thay đổi cách chúng tôi mở tệp. Bạn sẽ lưu ý rằng bây giờ

async with aiofiles.open(filename, 'wb') as fd:

Và chúng tôi sử dụng đang chờ phần viết mã:

await fd.write(chunk)

Ngoài ra, mã là như nhau. Có một số vấn đề về tính di động được đề cập ở đây mà bạn nên biết.

Kết thúc

Bây giờ bạn nên có một số hiểu biết cơ bản về cách sử dụng aiohttp và aiofiles. Tài liệu cho cả hai dự án rất đáng xem vì hướng dẫn này thực sự chỉ làm trầy xước bề mặt của những gì bạn có thể làm với các thư viện này.

6 hữu ích 0 bình luận 15k xem chia sẻ

Có thể bạn quan tâm

loading