Dalam Python, coroutine ialah kaedah pengaturcaraan serentak ringan yang boleh mencapai pelaksanaan serentak yang cekap melalui multitasking kolaboratif. Menggunakan kata kunci hasil untuk menggantung pelaksanaan fungsi dan menyimpan status pelaksanaan semasa ialah ciri khas coroutine. Oleh itu, coroutine boleh dianggap sebagai jenis fungsi penjana khas. Apabila coroutine digantung, pelaksanaannya boleh disambung semula menggunakan kaedah hantar dan nilai dikembalikan apabila disambung semula.
Sebelum Python 3.4, kata kunci hasil sering digunakan untuk melaksanakan coroutine, yang dipanggil "coroutine penjana". Selepas modul asyncio diperkenalkan dalam Python 3.4, anda boleh menggunakan kata kunci async/menunggu untuk menentukan fungsi coroutine, dipanggil "coroutine asli".
Berbanding dengan urutan dan proses, coroutine mempunyai kelebihan berikut:
Ringan: Kos penukaran konteks coroutine adalah sangat kecil dan boleh serentak dalam satu urutan. Laksanakan sejumlah besar coroutine.
Kependaman rendah: Semasa pelaksanaan coroutine, tiada overhed penukaran benang atau mengunci dan membuka kunci, membenarkan respons yang lebih pantas kepada peristiwa luaran.
Kecekapan: Kod Coroutine biasanya lebih ringkas dan boleh dibaca berbanding kod berbilang benang dan berbilang proses, serta mempunyai kos penyelenggaraan yang lebih rendah.
Senario penggunaan coroutine termasuk pengaturcaraan rangkaian, I/O tak segerak, pemprosesan aliran data, tugas konkurensi tinggi, dsb.
Dalam Python 3, Coroutine Penjana merujuk kepada coroutine yang dilaksanakan menggunakan fungsi penjana. Fungsi penjana ialah fungsi khas yang mengembalikan objek penjana Perlaksanaan fungsi boleh dijeda melalui pernyataan hasil, dan kemudian diteruskan apabila kaedah "next"() objek penjana dipanggil.
Berikut ialah contoh coroutine penjana ringkas, yang mengandungi coroutine fungsi penjana dan operasi I/O tak segerak ringkas:
import asyncio def coroutine(): print('Coroutine started') while True: result = yield print('Coroutine received:', result) async def main(): print('Main started') c = coroutine() next(c) c.send('Hello') await asyncio.sleep(1) c.send('World') print('Main finished') asyncio.run(main())
Keluaran hasil:
[root@workhost k8s]# python3 test.py
Utama dimulakan
Coroutine dimulakan
Coroutine diterima: Hello
Coroutine diterima: Dunia
Utama selesai
Mari kita lihat proses pelaksanaan kod di atas:
Fungsi utama mula melaksanakan dan mencetak Utama dimulakan.
Buat objek penjana c dan panggil seterusnya(c) untuk menjeda pelaksanaannya pada pernyataan hasil pertama.
Gunakan c.send('Hello') untuk menyambung semula pelaksanaan fungsi penjana dan gunakan 'Hello' sebagai nilai pulangan bagi fungsi penjana.
Semasa menunggu selama 1 saat, fungsi utama menjeda pelaksanaan dan menunggu gelung acara untuk memulakan tugas seterusnya.
Selepas menunggu selama 1 saat, gunakan c.send('World') untuk terus melaksanakan fungsi generator dan gunakan 'World' sebagai nilai pulangan bagi fungsi generator.
Fungsi utama menyambung semula pelaksanaan dan mencetak selesai Utama.
Dengan menggunakan coroutine fungsi penjana, kod ini melaksanakan coroutine mudah. Fungsi penjana menjeda pelaksanaan fungsi dengan menggunakan pernyataan hasil, yang kemudiannya boleh disambung semula melalui kaedah hantar, menghantar nilai kepada fungsi penjana. Dengan cara ini, anda boleh menggunakan fungsi penjana untuk mencapai konkurensi tak segerak. Gunakan fungsi penjana untuk menerima keputusan operasi I/O tak segerak dan mencetaknya, seperti yang ditunjukkan dalam contoh.
Python 3 memperkenalkan Coroutine Asli sebagai jenis coroutine baharu. Coroutine asli ditakrifkan dengan menggunakan kata kunci async/waiit, dan tidak seperti coroutine penjana, mereka boleh mengembalikan nilai seperti fungsi biasa menggunakan pernyataan pulangan dan bukannya menggunakan pernyataan hasil.
Berikut ialah contoh coroutine asli yang ringkas, yang mengandungi fungsi coroutine yang diubah suai dengan kata kunci tak segerak dan operasi I/O tak segerak yang ringkas:
import asyncio async def coroutine(): print('Coroutine started') await asyncio.sleep(1) print('Coroutine finished') async def main(): print('Main started') await coroutine() print('Main finished') asyncio.run(main())
Keluaran hasil:
[root@workhost k8s]# python3 test.py
Utama dimulakan
Coroutine dimulakan
Coroutine selesai
Utama selesai
Teruskan menonton Berikut ialah proses pelaksanaan :
Fungsi utama mula dilaksanakan dan mencetak Utama dimulakan.
Panggil fungsi coroutine dan jalankannya sebagai objek coroutine.
Dalam fungsi coroutine, cetak Coroutine dimulakan.
Dalam fungsi coroutine, gunakan await asyncio.sleep(1) untuk menjeda pelaksanaan fungsi dan tunggu selama 1 saat.
Selepas 1 saat, sambung semula pelaksanaan fungsi coroutine dan cetak Coroutine selesai.
Fungsi utama menyambung semula pelaksanaan dan mencetak selesai Utama.
Dalam kod di atas, coroutine fungsi coroutine asli ditakrifkan menggunakan kata kunci async, dan kata kunci await digunakan di dalamnya untuk menjeda pelaksanaan fungsi dan menunggu I/ tak segerak. O operasi penyiapan. Menggunakan coroutine asli membolehkan anda menulis kod tak segerak serentak, dengan itu meningkatkan kecekapan dan prestasi kod.
Python 3 中,原生协程和生成器协程是不同的协程实现方式,它们分别具有独特的特点和适用场景。下面,通过对比它们的区别和优缺点,才可以更好地理解它们之间的异同,以便选择适合自己的协程实现方式,从而更好地编写高效、可维护的异步程序。
1.区别:
定义方式不同:原生协程使用 async/await 关键字来定义,而生成器协程使用 yield 关键字来定义。
返回方式不同:原生协程使用 return 语句来返回结果,而生成器协程使用 yield 语句来返回结果。
调用方式不同:原生协程使用 await 关键字来调用,而生成器协程使用 yield from 或 yield 语句来调用。
原生协程与生成器协程的实现方式不同,前者使用 asyncio 库,后者则是 Python 语言内置的特性。
2.优缺点:
原生协程的优点:
代码简洁易懂:使用 async/await 关键字,可以编写出更简洁易懂的协程代码。
性能更高:原生协程不需要创建生成器对象,也不需要通过 yield 语句来控制函数的执行流程,因此能够更加高效地处理异步操作。
支持异步 I/O 和任务处理:原生协程可以支持异步 I/O 操作和并发任务处理,可以在处理异步操作时更加灵活。
原生协程的缺点:
兼容性差:原生协程是 Python 3.5 版本之后才引入的新特性,因此在旧版本的 Python 中无法使用。
异常处理不方便:原生协程在处理异常时比较麻烦,需要使用 try/except 语句来处理。
生成器协程的优点:
兼容性好:生成器协程是 Python 2 和 Python 3 都支持的特性。
可读性好:生成器协程使用 yield 关键字来实现,代码逻辑清晰易懂。
异常处理方便:生成器协程在处理异常时比较方便,可以使用 try/except 语句来处理。
生成器协程的缺点:
性能相对较低:生成器协程需要创建生成器对象,也需要通过 yield 语句来控制函数的执行流程,因此处理异步操作时性能相对较低。
功能有限:生成器协程不能像原生协程一样支持异步 I/O 操作和任务处理。
接下来,模拟一个场景,假设实现一个异步的批量处理任务的工具,使用原生协程来实现。
看下面代码:
import asyncio import random async def batch_process_task(tasks, batch_size=10): # 将任务列表划分为多个批次 for i in range(0, len(tasks), batch_size): batch = tasks[i:i+batch_size] # 使用原生协程来异步处理每个批次的任务 await asyncio.gather(*[process_task(task) for task in batch]) async def process_task(task): # 模拟任务处理过程 await asyncio.sleep(random.uniform(0.5, 2.0)) print("Task {} processed".format(task)) async def main(): # 构造任务列表 tasks = [i for i in range(1, 101)] # 并发处理批量任务 await batch_process_task(tasks, batch_size=10) if __name__ == '__main__': asyncio.run(main())
输出:
[root@workhost k8s]# python3 test.py
Task 9 processed
Task 10 processed
Task 1 processed
Task 8 processed
Task 6 processed
Task 4 processed
Task 3 processed
Task 2 processed
Task 5 processed
...
...
batch_process_task函数使用原生协程来处理每个批次的任务,而process_task函数则是处理每个任务的函数。在main函数中,任务列表会被构造,并使用batch_process_task函数来异步地处理批量任务。
Atas ialah kandungan terperinci Apakah kaedah pelaksanaan coroutine Python?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!