Rumah >pembangunan bahagian belakang >Tutorial Python >Menguasai Koroutine Python: Tingkatkan Kecekapan dan Prestasi Kod Anda
Mari kita terokai dunia coroutine yang menarik dan konkurensi berstruktur dalam Python. Ciri berkuasa ini telah merevolusikan cara kami menulis kod serentak, menjadikannya lebih cekap dan lebih mudah untuk diurus.
Coroutine ialah fungsi khas yang boleh menjeda pelaksanaannya dan menghasilkan kawalan kepada coroutine lain. Ia ditakrifkan menggunakan kata kunci async dan boleh ditunggu menggunakan kata kunci tunggu. Berikut ialah contoh mudah:
async def greet(name): print(f"Hello, {name}!") await asyncio.sleep(1) print(f"Goodbye, {name}!") async def main(): await greet("Alice") await greet("Bob") asyncio.run(main())
Dalam kod ini, fungsi salam ialah coroutine yang mencetak ucapan, menunggu seketika, dan kemudian mengucapkan selamat tinggal. Panggilan fungsi utama memberi salam dua kali, dan kami menggunakan asyncio.run untuk melaksanakan coroutine utama.
Tetapi apakah yang membuatkan coroutine begitu istimewa? Mereka membenarkan kami menulis kod serentak yang kelihatan dan berkelakuan seperti kod segerak, tetapi sebenarnya boleh melaksanakan berbilang operasi serentak. Ini amat berguna untuk tugas terikat I/O, seperti operasi rangkaian atau pengendalian fail.
Mari kita mendalami perpustakaan asyncio, yang menyediakan asas untuk pengaturcaraan tak segerak dalam Python. Pada terasnya ialah gelung acara, yang menguruskan pelaksanaan coroutine. Anda boleh menganggapnya sebagai penjadual yang menentukan coroutine yang akan dijalankan seterusnya.
Begini cara kami boleh mencipta dan menggunakan tugasan dengan asyncio:
import asyncio async def fetch_data(url): print(f"Fetching data from {url}") await asyncio.sleep(2) # Simulating network delay return f"Data from {url}" async def main(): urls = ['http://example.com', 'http://example.org', 'http://example.net'] tasks = [asyncio.create_task(fetch_data(url)) for url in urls] results = await asyncio.gather(*tasks) for result in results: print(result) asyncio.run(main())
Dalam contoh ini, kami mensimulasikan pengambilan data daripada berbilang URL secara serentak. Fungsi asyncio.create_task menukar coroutine kami kepada tugas, yang kemudiannya dilaksanakan serentak menggunakan asyncio.gather.
Sekarang, mari kita bincangkan tentang konkurensi berstruktur. Ini adalah paradigma yang bertujuan untuk menjadikan kod serentak lebih mudah diramal dan lebih mudah untuk difikirkan. Python 3.11 memperkenalkan beberapa ciri baharu untuk menyokong konkurensi berstruktur, seperti kumpulan tugas.
Begini cara kita boleh menggunakan kumpulan tugas:
import asyncio async def process_item(item): await asyncio.sleep(1) return f"Processed {item}" async def main(): async with asyncio.TaskGroup() as tg: task1 = tg.create_task(process_item("A")) task2 = tg.create_task(process_item("B")) task3 = tg.create_task(process_item("C")) print(task1.result()) print(task2.result()) print(task3.result()) asyncio.run(main())
Kumpulan Tugas memastikan semua tugasan selesai (atau dibatalkan) sebelum kami meneruskan. Ini membantu mengelakkan isu seperti tugas yang terlupa atau interaksi yang tidak dijangka antara operasi serentak.
Salah satu aspek coroutine yang paling berkuasa ialah keupayaan mereka untuk mengendalikan operasi I/O dengan cekap. Mari lihat contoh pelayan web tak segerak yang mudah:
import asyncio from aiohttp import web async def handle(request): name = request.match_info.get('name', "Anonymous") text = f"Hello, {name}!" return web.Response(text=text) async def main(): app = web.Application() app.add_routes([web.get('/', handle), web.get('/{name}', handle)]) runner = web.AppRunner(app) await runner.setup() site = web.TCPSite(runner, 'localhost', 8080) await site.start() print("Server started at http://localhost:8080") await asyncio.Event().wait() asyncio.run(main())
Pelayan ini boleh mengendalikan berbilang sambungan secara serentak, terima kasih kepada kuasa coroutine. Setiap permintaan diproses dalam coroutine tersendiri, membolehkan pelayan kekal responsif walaupun di bawah beban yang tinggi.
Mari kita teroka beberapa konsep yang lebih maju. Pembatalan adalah ciri penting apabila berurusan dengan operasi serentak. Kadangkala kita perlu menghentikan sesuatu tugasan sebelum ia selesai. Begini cara kami boleh melakukannya:
async def greet(name): print(f"Hello, {name}!") await asyncio.sleep(1) print(f"Goodbye, {name}!") async def main(): await greet("Alice") await greet("Bob") asyncio.run(main())
Dalam contoh ini, kami mencipta tugasan yang berjalan lama dan membatalkannya selepas 5 saat. Tugasan menangkap CancelledError dan melakukan sebarang pembersihan yang diperlukan sebelum keluar.
Ciri hebat lain ialah keupayaan untuk mencipta gelung acara tersuai. Walaupun gelung peristiwa lalai mencukupi untuk kebanyakan kes, kadangkala kita memerlukan lebih kawalan. Berikut ialah contoh mudah gelung acara tersuai:
import asyncio async def fetch_data(url): print(f"Fetching data from {url}") await asyncio.sleep(2) # Simulating network delay return f"Data from {url}" async def main(): urls = ['http://example.com', 'http://example.org', 'http://example.net'] tasks = [asyncio.create_task(fetch_data(url)) for url in urls] results = await asyncio.gather(*tasks) for result in results: print(result) asyncio.run(main())
Ini ialah gelung acara tersuai yang sangat asas, tetapi ia menunjukkan prinsipnya. Anda boleh melanjutkan ini untuk menambah ciri seperti penjadualan, pemantauan atau penyepaduan yang lebih baik dengan sistem lain.
Mari kita bincangkan tentang beberapa amalan terbaik apabila bekerja dengan coroutine dan konkurensi berstruktur. Pertama, sentiasa gunakan async with untuk mengurus pengurus konteks tak segerak. Ini memastikan persediaan dan pembongkaran yang betul, walaupun terdapat pengecualian:
import asyncio async def process_item(item): await asyncio.sleep(1) return f"Processed {item}" async def main(): async with asyncio.TaskGroup() as tg: task1 = tg.create_task(process_item("A")) task2 = tg.create_task(process_item("B")) task3 = tg.create_task(process_item("C")) print(task1.result()) print(task2.result()) print(task3.result()) asyncio.run(main())
Kedua, berhati-hati dengan operasi menyekat. Jika anda perlu melaksanakan tugas terikat CPU, pertimbangkan untuk menggunakan asyncio.to_thread untuk menjalankannya dalam urutan berasingan:
import asyncio from aiohttp import web async def handle(request): name = request.match_info.get('name', "Anonymous") text = f"Hello, {name}!" return web.Response(text=text) async def main(): app = web.Application() app.add_routes([web.get('/', handle), web.get('/{name}', handle)]) runner = web.AppRunner(app) await runner.setup() site = web.TCPSite(runner, 'localhost', 8080) await site.start() print("Server started at http://localhost:8080") await asyncio.Event().wait() asyncio.run(main())
Ketiga, gunakan asyncio.wait apabila anda memerlukan lebih kawalan ke atas sekumpulan tugas. Ia membolehkan anda menunggu tugas pertama selesai, atau menetapkan tamat masa:
import asyncio async def long_running_task(): try: while True: print("Working...") await asyncio.sleep(1) except asyncio.CancelledError: print("Task was cancelled") async def main(): task = asyncio.create_task(long_running_task()) await asyncio.sleep(5) task.cancel() try: await task except asyncio.CancelledError: print("Main: task was cancelled") asyncio.run(main())
Menyahpepijat kod serentak boleh menjadi mencabar. Asyncio Python disertakan dengan beberapa alat yang berguna. Anda boleh mendayakan mod nyahpepijat untuk mendapatkan pengelogan yang lebih terperinci:
import asyncio class MyEventLoop(asyncio.BaseEventLoop): def __init__(self): self._running = False self._ready = asyncio.Queue() def run_forever(self): self._running = True while self._running: coro = self._ready.get_nowait() if coro: coro.send(None) def stop(self): self._running = False def call_soon(self, callback, *args): self._ready.put_nowait(callback(*args)) # Usage loop = MyEventLoop() asyncio.set_event_loop(loop) async def my_coroutine(): print("Hello from my coroutine!") loop.call_soon(my_coroutine) loop.run_forever()
Anda juga boleh menggunakan pustaka aiodebug untuk ciri nyahpepijat yang lebih maju.
Mari kita lihat contoh yang lebih kompleks: saluran paip pemprosesan data selari. Ini mungkin berguna untuk tugas seperti memproses set data yang besar atau mengendalikan data penstriman:
async with aiohttp.ClientSession() as session: async with session.get('http://example.com') as response: html = await response.text()
Saluran paip ini menunjukkan cara kami boleh menggunakan baris gilir untuk menghantar data antara peringkat pemprosesan yang berbeza, semuanya berjalan serentak.
Coroutine dan konkurensi berstruktur telah membuka kemungkinan baharu dalam pengaturcaraan Python. Mereka membenarkan kami menulis kod serentak yang cekap dan lebih mudah untuk difikirkan dan diselenggara. Sama ada anda membina pelayan web, saluran paip pemprosesan data atau GUI responsif, alatan ini boleh membantu anda mencipta aplikasi yang mantap dan berprestasi tinggi.
Ingat, kunci untuk menguasai konsep ini adalah amalan. Mulakan dengan contoh mudah dan secara beransur-ansur membina kes penggunaan yang lebih kompleks. Beri perhatian kepada pengendalian dan pembatalan ralat, kerana ini penting untuk membina sistem tak segerak yang boleh dipercayai. Dan jangan takut untuk menyelami kod sumber asyncio – ini cara yang bagus untuk memperdalam pemahaman anda tentang cara ciri berkuasa ini berfungsi di bawah hud.
Sambil anda terus meneroka coroutine dan konkurensi berstruktur, anda akan menemui corak dan teknik baharu yang boleh menjadikan kod anda lebih cekap dan ekspresif. Ia merupakan bidang pembangunan Python yang menarik, dan yang sentiasa berkembang. Jadi teruskan belajar, teruskan percubaan dan nikmati perjalanan ke dunia pengaturcaraan tak segerak!
Pastikan anda melihat ciptaan kami:
Pusat Pelabur | Hidup Pintar | Epos & Gema | Misteri Membingungkan | Hindutva | Pembangunan Elit | Sekolah JS
Tech Koala Insights | Dunia Epok & Gema | Medium Pusat Pelabur | Medium Misteri Membingungkan | Sains & Zaman Sederhana | Hindutva Moden
Atas ialah kandungan terperinci Menguasai Koroutine Python: Tingkatkan Kecekapan dan Prestasi Kod Anda. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!