Rumah > Artikel > pembangunan bahagian belakang > Sungguh artifak! Rangka kerja perangkak Python yang cekap yang lebih mudah digunakan daripada permintaan!
Baru-baru ini, projek back-end Python syarikat telah disusun semula, dan keseluruhan logik back-end pada dasarnya telah ditukar untuk menggunakan pelaksanaan coroutine "tak segerak". Melihat skrin yang penuh dengan kod yang dihiasi dengan async menanti (pelaksanaan coroutine dalam Python), saya tiba-tiba berasa keliru dan bingung.
Walaupun saya telah belajar tentang apa itu "coroutine" sebelum ini, saya belum menerokainya secara mendalam, jadi saya hanya mengambil peluang ini untuk mempelajarinya dengan teliti.
Jom
Ringkasnya, coroutine adalah berdasarkan benang tetapi lebih ringan daripada benang. Untuk kernel sistem, coroutine mempunyai ciri yang tidak kelihatan, jadi benang ringan ini yang diuruskan oleh pengaturcara yang menulis program mereka sendiri sering dipanggil "benang ruang pengguna".
1. Kawalan benang berada di tangan sistem pengendalian, manakala kawalan coroutine sepenuhnya berada di tangan pengguna Oleh itu, menggunakan coroutine boleh mengurangkan penukaran konteks semasa program dijalankan , dan meningkatkan kecekapan program dengan berkesan.
2. Apabila mencipta benang, saiz tindanan lalai yang diperuntukkan kepada benang oleh sistem ialah 1 M, manakala coroutine lebih ringan, menghampiri 1 K, jadi lebih banyak coroutine boleh dibuka dalam memori yang sama.
3. Memandangkan sifat coroutine bukan berbilang benang tetapi berbenang tunggal, tidak perlu mekanisme kunci berbilang benang. Kerana hanya terdapat satu utas, tiada konflik yang disebabkan oleh penulisan pembolehubah pada masa yang sama. Mengawal sumber yang dikongsi dalam coroutine tidak memerlukan penguncian, hanya status yang perlu ditentukan. Oleh itu, kecekapan pelaksanaan coroutine jauh lebih tinggi daripada multi-threads, dan ia juga berkesan mengelakkan persaingan dalam multi-threads.
Senario Berkenaan: Coroutines sesuai untuk senario yang disekat dan memerlukan sejumlah besar konkurensi.
Senario yang tidak boleh digunakan: Coroutine tidak sesuai untuk senario dengan jumlah pengiraan yang besar (kerana intipati coroutine adalah untuk bertukar-tukar dalam satu urutan Jika anda menghadapi situasi ini, anda harus menggunakan yang lain). bermaksud menyelesaikannya.
Pada ketika ini kita sepatutnya mempunyai pemahaman umum tentang "coroutine", tetapi pada ketika ini dalam cerita, saya percaya beberapa rakan masih penuh keraguan: "coroutine" Bagaimanakah ia membantu dengan ujian antara muka? Jangan risau, jawapannya ada di bawah.
Saya percaya bahawa rakan yang telah menggunakan Python untuk ujian antara muka sudah biasa dengan perpustakaan permintaan. Permintaan http yang dilaksanakan dalam permintaan ialah permintaan segerak, tetapi sebenarnya, berdasarkan ciri penyekat IO permintaan http, adalah sangat sesuai untuk menggunakan coroutine untuk melaksanakan permintaan http "tak segerak" untuk meningkatkan kecekapan ujian.
Saya percaya seseorang telah menyedari perkara ini lama dahulu, jadi selepas beberapa penerokaan di Github, seperti yang dijangkakan, akhirnya saya menemui perpustakaan sumber terbuka yang menyokong coroutine untuk memanggil "secara tidak segerak" http: httpx.
httpx ialah perpustakaan sumber terbuka yang mewarisi hampir semua ciri permintaan dan menyokong permintaan http "tak segerak". Ringkasnya, httpx boleh dianggap sebagai versi permintaan yang dipertingkatkan.
Kini anda boleh mengikuti saya untuk melihat kekuatan httpx.
Pemasangan httpx adalah sangat mudah dan boleh dilaksanakan dalam persekitaran Python 3.6 atau lebih tinggi.
pip install httpx
Bak kata pepatah, kecekapan menentukan kejayaan atau kegagalan. Saya menggunakan kaedah httpx asynchronous dan synchronous untuk membandingkan penggunaan masa permintaan http batch Mari kita lihat hasilnya~
Pertama, mari kita lihat prestasi yang memakan masa permintaan http segerak:
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)
Kod ini agak mudah Anda boleh melihat bahawa dalam sync_main, akses http segerak ke Baidu dilaksanakan sebanyak 200 kali.
Output selepas dijalankan adalah seperti berikut (sebahagian daripada output kunci dipintas...):
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
Anda boleh melihat bahawa dalam output di atas, utas utama tidak dihidupkan (kerana asalnya ia adalah satu utas Ah!) Permintaan dilaksanakan mengikut urutan (kerana ia adalah permintaan segerak).
Program ini mengambil masa selama 16.6 saat untuk dijalankan.
Mari cuba permintaan http "asynchronous" di bawah:
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)
Kod di atas menggunakan kata kunci async await dalam async_main untuk melaksanakan http "asynchronous" dan meminta Baidu melalui asyncio (pustaka io asynchronous Laman utama 200 kali dan cetak masa yang diambil).
Selepas menjalankan kod, anda boleh melihat output berikut (beberapa output utama telah dipintas...).
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
Anda dapat melihat bahawa walaupun susunannya berantakan (56, 99, 67...) (ini kerana program terus bertukar antara coroutine), utas utama tidak bertukar (intipati daripada coroutine) Masih berbenang tunggal).
Proses mengambil masa 4.5 saat secara keseluruhan.
Berbanding dengan 16.6 saat yang diambil oleh permintaan segerak, ia dipendekkan hampir 73%!
Bak kata pepatah, satu langkah itu pantas, dan setiap langkah itu pantas. Dari segi penggunaan masa, httpx "tak segerak" sememangnya jauh lebih pantas daripada http segerak. Sudah tentu, "coroutines" bukan sahaja boleh membolehkan ujian antara muka dari segi kecekapan permintaan Selepas menguasai "coroutines", saya percaya bahawa tahap teknikal rakan juga boleh ditingkatkan ke tahap yang lebih tinggi, dengan itu mereka bentuk rangka kerja ujian yang lebih baik.
Baiklah, ini sahaja kandungan yang dikongsikan hari ini, jika anda suka, sila beri like~
Atas ialah kandungan terperinci Sungguh artifak! Rangka kerja perangkak Python yang cekap yang lebih mudah digunakan daripada permintaan!. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!