>  기사  >  백엔드 개발  >  비동기 컨텍스트 관리자 마스터하기: Python 코드 성능 향상

비동기 컨텍스트 관리자 마스터하기: Python 코드 성능 향상

Susan Sarandon
Susan Sarandon원래의
2024-11-26 14:18:11908검색

Mastering Async Context Managers: Boost Your Python Code

Python의 비동기 컨텍스트 관리자는 동시 애플리케이션에서 리소스를 처리하는 획기적인 도구입니다. 일반 컨텍스트 관리자와 비슷하지만, 비동기 코드와 원활하게 작동한다는 점이 다릅니다.

기본부터 시작하겠습니다. 비동기 컨텍스트 관리자를 생성하려면 __aenter__ 및 __aexit__라는 두 가지 특수 메서드를 구현해야 합니다. 이는 일반 컨텍스트 관리자에서 사용하는 __enter__ 및 __exit__의 비동기 버전입니다.

다음은 간단한 예입니다.

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())

이 예에서는 리소스의 비동기 획득 및 해제를 시뮬레이션합니다. async with 문은 적절한 시점에 __aenter__ 및 __aexit__ 호출을 처리합니다.

이제 비동기 컨텍스트 관리자가 왜 그렇게 유용한지 이야기해 보겠습니다. 데이터베이스 연결, 네트워크 소켓 또는 파일 처리기와 같은 비동기 작업이 필요한 리소스를 비차단 방식으로 관리하는 데 적합합니다.

예를 들어 데이터베이스 연결을 생각해 보세요. 연결 풀을 관리하는 비동기 컨텍스트 관리자를 만들 수 있습니다.

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())

이 설정을 통해 데이터베이스 연결을 효율적으로 관리할 수 있습니다. 풀은 컨텍스트에 들어갈 때 생성되고 나갈 때 적절하게 닫힙니다.

비동기 컨텍스트 관리자의 오류 처리는 일반 컨텍스트 관리자와 유사합니다. __aexit__ 메서드는 컨텍스트 내에서 오류가 발생하는 경우 예외 정보를 받습니다. 이러한 오류를 처리하거나 전파되도록 할 수 있습니다.

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())

이 예에서는 ValueError를 억제하지만 다른 예외가 전파되도록 허용합니다.

비동기 컨텍스트 관리자는 분산 잠금을 구현하는 데에도 적합합니다. 다음은 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())

이 잠금을 사용하면 여러 시스템에서도 한 번에 하나의 프로세스만 중요 섹션을 실행할 수 있습니다.

트랜잭션 범위에 비동기 컨텍스트 관리자를 사용할 수도 있습니다.

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)

이 설정을 사용하면 예외가 발생하더라도 데이터베이스 트랜잭션이 항상 적절하게 커밋되거나 롤백됩니다.

비동기 컨텍스트 관리자는 더욱 강력한 패턴을 위해 다른 비동기 기본 요소와 결합될 수 있습니다. 예를 들어 병렬 리소스 관리를 위해 asyncio.gather와 함께 사용할 수 있습니다.

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

이를 통해 적절한 리소스 관리를 보장하면서 동시에 여러 데이터 조각을 처리할 수 있습니다.

결론적으로 비동기 컨텍스트 관리자는 비동기 Python 코드에서 리소스를 관리하기 위한 강력한 도구입니다. 비동기 설정 및 해제, 오류 처리, 리소스 정리를 처리하는 깔끔하고 직관적인 방법을 제공합니다. 비동기 컨텍스트 관리자를 마스터하면 복잡한 동시 워크플로를 쉽게 처리할 수 있는 강력하고 확장 가능한 Python 애플리케이션을 구축할 수 있는 준비를 갖추게 됩니다.


우리의 창조물

저희 창작물을 꼭 확인해 보세요.

인베스터 센트럴 | 스마트리빙 | 시대와 메아리 | 수수께끼의 미스터리 | 힌두트바 | 엘리트 개발자 | JS 학교


우리는 중간에 있습니다

테크 코알라 인사이트 | Epochs & Echoes World | 투자자중앙매체 | 수수께끼 미스터리 매체 | 과학과 신기원 매체 | 현대 힌두트바

위 내용은 비동기 컨텍스트 관리자 마스터하기: Python 코드 성능 향상의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.