ホームページ  >  記事  >  バックエンド開発  >  なんという芸術品でしょう!リクエストよりも使いやすい、効率的な Python クローラー フレームワークです。

なんという芸術品でしょう!リクエストよりも使いやすい、効率的な Python クローラー フレームワークです。

WBOY
WBOY転載
2023-04-13 14:25:031421ブラウズ

なんという芸術品でしょう!リクエストよりも使いやすい、効率的な Python クローラー フレームワークです。

最近、同社の Python バックエンド プロジェクトが再構築され、バックエンド ロジック全体が基本的に「非同期」コルーチンを使用するように変更されました。 async await (Python のコルーチンの実装) で装飾されたコードが画面いっぱいに表示されているのを見て、私は突然混乱して途方に暮れました。

「コルーチン」とは何かについては以前に学んだことがありますが、詳しく調べたことはなかったので、この機会に学んでみました。

さあ行きましょう

なんという芸術品でしょう!リクエストよりも使いやすい、効率的な Python クローラー フレームワークです。

コルーチンとは何ですか?

簡単に言えば、コルーチンはスレッドに基づいていますが、スレッドよりも軽量です。システム カーネルの場合、コルーチンには目に見えない特性があるため、独自のプログラムを作成するプログラマによって管理されるこの軽量スレッドは、多くの場合「ユーザー空間スレッド」と呼ばれます。

マルチスレッドに対するコルーチンの利点は何ですか?

1. スレッドの制御はオペレーティング システムの手にあり、コルーチンの制御は完全にユーザーの手にあります。そのため、コルーチンを使用すると、プログラム実行中のコンテキストの切り替えが減少し、プログラムを効果的に改善できます。走行効率。

2. スレッドの作成時に、システムによってスレッドに割り当てられるデフォルトのスタック サイズは 1 M ですが、コルーチンはより軽量で 1 K に近いため、同じメモリ内でより多くのコルーチンを開くことができます。

3. コルーチンの性質はマルチスレッドではなくシングルスレッドであるため、マルチスレッドのロック機構は必要ありません。スレッドが 1 つしかないため、変数の同時書き込みによる競合が発生しません。コルーチン内の共有リソースの制御にはロックは必要なく、ステータスを決定するだけで済みます。したがって、コルーチンの実行効率はマルチスレッドの実行効率よりもはるかに高く、マルチスレッドでの競合も効果的に回避します。

コルーチンの適用可能なシナリオと適用できないシナリオ

適用可能なシナリオ: コルーチンは、ブロックされ、大量の同時実行を必要とするシナリオに適しています。

適用できないシナリオ: コルーチンは、大量の計算を伴うシナリオには適していません (コルーチンの本質は単一スレッド内で前後に切り替えることであるため)。この状況が発生した場合でも、他のものを使用する必要があります。それを解決するという意味です。

非同期 http フレームワークの最初の探索 httpx

この時点で、「コルーチン」について一般的な理解が得られているはずですが、この話のこの時点では、まだ理解できていない人もいると思います。疑問: 「コルーチン」 インターフェイスのテストにどのように役立ちますか?心配しないでください。答えは以下にあります。

インターフェイス テストに Python を使用したことのある友人は、リクエスト ライブラリに精通していると思います。リクエストに実装されている http リクエストは同期リクエストですが、実際には、http リクエストの IO ブロック特性に基づいて、コルーチンを使用して「非同期」 http リクエストを実装し、テスト効率を向上させることが非常に適しています。

誰かがずっと前にこれに気づいていたと思うので、Github を調べた結果、予想通り、http: httpx のコルーチンの「非同期」呼び出しをサポートするオープン ソース ライブラリを最終的に見つけました。

httpx

httpx とは、リクエストのほぼすべての機能を継承し、「非同期」http リクエストをサポートするオープン ソース ライブラリです。簡単に言えば、httpx はリクエストの拡張版と考えることができます。

これで、誰でも私をフォローして httpx の威力を確認できるようになります。

インストール

httpx のインストールは非常に簡単で、Python 3.6 以降の環境で実行できます。

pip install httpx

ベスト プラクティス

よく言われるように、効率が成功か失敗かを決定します。 httpx 非同期メソッドと同期メソッドを使用して、バッチ http リクエストの消費時間を比較しました。結果を見てみましょう~

まず、同期 http リクエストの時間のかかるパフォーマンスを見てみましょう:

import asyncio
import httpx
import threading
import time
def sync_main(url, sign):
 response = httpx.get(url).status_code
 print(f'sync_main: {threading.current_thread()}: {sign}2 + 1{response}')
sync_start = time.time()
[sync_main(url='http://www.baidu.com', sign=i) for i in range(200)]
sync_end = time.time()
print(sync_end - sync_start)

コードは比較的単純ですが、sync_main では Baidu への http 同期アクセスが 200 回実装されていることがわかります。

実行後の出力は次のとおりです (キー出力の一部がインターセプトされています...):

sync_main: <_MainThread(MainThread, started 4471512512)>: 192: 200
sync_main: <_MainThread(MainThread, started 4471512512)>: 193: 200
sync_main: <_MainThread(MainThread, started 4471512512)>: 194: 200
sync_main: <_MainThread(MainThread, started 4471512512)>: 195: 200
sync_main: <_MainThread(MainThread, started 4471512512)>: 196: 200
sync_main: <_MainThread(MainThread, started 4471512512)>: 197: 200
sync_main: <_MainThread(MainThread, started 4471512512)>: 198: 200
sync_main: <_MainThread(MainThread, started 4471512512)>: 199: 200
16.56578803062439

上記の出力では、メイン スレッドが切り替えられていないことがわかります。元々は単一のスレッドです) !) リクエストは順番に実行されます (同期リクエストであるため)。

プログラムの実行には合計 16.6 秒かかりました。

以下の「非同期」 http リクエストを試してみましょう:

import asyncio
import httpx
import threading
import time
client = httpx.AsyncClient()
async def async_main(url, sign):
 response = await client.get(url)
 status_code = response.status_code
 print(f'async_main: {threading.current_thread()}: {sign}:{status_code}')
loop = asyncio.get_event_loop()
tasks = [async_main(url='http://www.baidu.com', sign=i) for i in range(200)]
async_start = time.time()
loop.run_until_complete(asyncio.wait(tasks))
async_end = time.time()
loop.close()
print(async_end - async_start)

上記のコードは、async_main の async await キーワードを使用して「非同期」 http を実装し、asyncio (非同期 io ライブラリ) を通じて Baidu ホームページ 200 をリクエストします。所要時間を印刷してください)。

コードを実行すると、次の出力が表示されます (一部のキー出力がインターセプトされています...)。

async_main: <_MainThread(MainThread, started 4471512512)>: 56: 200
async_main: <_MainThread(MainThread, started 4471512512)>: 99: 200
async_main: <_MainThread(MainThread, started 4471512512)>: 67: 200
async_main: <_MainThread(MainThread, started 4471512512)>: 93: 200
async_main: <_MainThread(MainThread, started 4471512512)>: 125: 200
async_main: <_MainThread(MainThread, started 4471512512)>: 193: 200
async_main: <_MainThread(MainThread, started 4471512512)>: 100: 200
4.518340110778809

順序がめちゃくちゃになっている (56、99、67...) (これは、プログラムがコルーチン間を切り替え続けるため) にもかかわらず、メイン スレッドが切り替わらないことがわかります (これが、コルーチンはまだシングルスレッドです)。

この手順には合計 4.5 秒かかりました。

同期リクエストにかかる 16.6 秒と比較すると、73% 近く短縮されています。

格言にあるように、1 つのステップは速く、すべてのステップも速いです。時間の消費という点では、「非同期」httpx は同期 http よりも実際にはるかに高速です。もちろん、「コルーチン」はリクエスト効率の面でインターフェーステストができるだけではなく、「コルーチン」を使いこなすことで仲間の技術レベルをより高いレベルに高めることができ、より良いテストフレームワークを設計できると思います。

さて、これが今日共有したすべてのコンテンツです。気に入っていただけましたら、「いいね」をお願いします~

以上がなんという芸術品でしょう!リクエストよりも使いやすい、効率的な Python クローラー フレームワークです。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事は51cto.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。