Rumah >pembangunan bahagian belakang >Tutorial Python >Menguasai Pengurus Konteks Async: Tingkatkan Prestasi Kod Python Anda
Pengurus konteks tak segerak dalam Python ialah penukar permainan untuk mengendalikan sumber dalam aplikasi serentak. Mereka seperti pengurus konteks biasa, tetapi dengan kelainan - mereka berfungsi dengan lancar dengan kod async.
Mari kita mulakan dengan perkara asas. Untuk mencipta pengurus konteks async, kita perlu melaksanakan dua kaedah khas: __aenter__ dan __aexit__. Ini ialah versi async __enter__ dan __exit__ yang kami gunakan dalam pengurus konteks biasa.
Berikut ialah contoh mudah:
class AsyncResource: async def __aenter__(self): print("Acquiring resource") await asyncio.sleep(1) # Simulating async acquisition return self async def __aexit__(self, exc_type, exc_value, traceback): print("Releasing resource") await asyncio.sleep(1) # Simulating async release async def main(): async with AsyncResource() as resource: print("Using resource") asyncio.run(main())
Dalam contoh ini, kami mensimulasikan pemerolehan async dan keluaran sumber. Pernyataan async dengan mengurus panggilan __aenter__ dan __aexit__ pada masa yang betul.
Sekarang, mari kita bincangkan tentang sebab pengurus konteks async sangat berguna. Ia sesuai untuk mengurus sumber yang memerlukan operasi tak segerak, seperti sambungan pangkalan data, soket rangkaian atau pengendali fail tanpa menyekat.
Ambil sambungan pangkalan data, contohnya. Kami boleh mencipta pengurus konteks async yang mengurus kumpulan sambungan:
import asyncpg class DatabasePool: def __init__(self, dsn): self.dsn = dsn self.pool = None async def __aenter__(self): self.pool = await asyncpg.create_pool(self.dsn) return self.pool async def __aexit__(self, exc_type, exc_value, traceback): await self.pool.close() async def main(): async with DatabasePool('postgresql://user:password@localhost/db') as pool: async with pool.acquire() as conn: result = await conn.fetch('SELECT * FROM users') print(result) asyncio.run(main())
Persediaan ini memastikan kami menguruskan sambungan pangkalan data kami dengan cekap. Kolam itu dicipta apabila kita memasuki konteks dan ditutup dengan betul apabila kita keluar.
Ralat pengendalian dalam pengurus konteks async adalah serupa dengan pengurus biasa. Kaedah __aexit__ menerima maklumat pengecualian jika ralat berlaku dalam konteks. Kami boleh menangani ralat ini atau membiarkannya merebak:
class ErrorHandlingResource: async def __aenter__(self): return self async def __aexit__(self, exc_type, exc_value, traceback): if exc_type is ValueError: print("Caught ValueError, suppressing") return True # Suppress the exception return False # Let other exceptions propagate async def main(): async with ErrorHandlingResource(): raise ValueError("Oops!") print("This will be printed") async with ErrorHandlingResource(): raise RuntimeError("Unhandled!") print("This won't be printed") asyncio.run(main())
Dalam contoh ini, kami menyekat ValueError tetapi membenarkan pengecualian lain untuk disebarkan.
Pengurus konteks Async juga bagus untuk melaksanakan kunci teragih. Berikut ialah contoh mudah menggunakan Redis:
import aioredis class DistributedLock: def __init__(self, redis, lock_name, expire=10): self.redis = redis self.lock_name = lock_name self.expire = expire async def __aenter__(self): while True: locked = await self.redis.set(self.lock_name, "1", expire=self.expire, nx=True) if locked: return self await asyncio.sleep(0.1) async def __aexit__(self, exc_type, exc_value, traceback): await self.redis.delete(self.lock_name) async def main(): redis = await aioredis.create_redis_pool('redis://localhost') async with DistributedLock(redis, "my_lock"): print("Critical section") await redis.close() asyncio.run(main())
Kunci ini memastikan hanya satu proses boleh melaksanakan bahagian kritikal pada satu masa, walaupun merentasi berbilang mesin.
Kami juga boleh menggunakan pengurus konteks async untuk skop transaksi:
class AsyncTransaction: def __init__(self, conn): self.conn = conn async def __aenter__(self): await self.conn.execute('BEGIN') return self async def __aexit__(self, exc_type, exc_value, traceback): if exc_type is None: await self.conn.execute('COMMIT') else: await self.conn.execute('ROLLBACK') async def transfer_funds(from_account, to_account, amount): async with AsyncTransaction(conn): await conn.execute('UPDATE accounts SET balance = balance - WHERE id = ', amount, from_account) await conn.execute('UPDATE accounts SET balance = balance + WHERE id = ', amount, to_account)
Persediaan ini memastikan transaksi pangkalan data kami sentiasa dilakukan atau ditarik balik dengan betul, walaupun dalam menghadapi pengecualian.
Pengurus konteks async boleh digabungkan dengan primitif async lain untuk corak yang lebih berkuasa. Sebagai contoh, kita boleh menggunakannya dengan asyncio.gather untuk pengurusan sumber selari:
async def process_data(data): async with ResourceManager() as rm: results = await asyncio.gather( rm.process(data[0]), rm.process(data[1]), rm.process(data[2]) ) return results
Ini membolehkan kami memproses berbilang keping data secara selari sambil memastikan pengurusan sumber yang betul.
Kesimpulannya, pengurus konteks async ialah alat yang berkuasa untuk mengurus sumber dalam kod Python tak segerak. Mereka menyediakan cara yang bersih dan intuitif untuk mengendalikan persediaan async dan teardown, pengendalian ralat dan pembersihan sumber. Dengan menguasai pengurus konteks async, anda akan dilengkapi dengan baik untuk membina aplikasi Python yang teguh dan berskala yang boleh mengendalikan aliran kerja serentak yang kompleks dengan mudah.
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 Pengurus Konteks Async: Tingkatkan Prestasi Kod Python Anda. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!