반응형
파이썬의 비동기 프로그래밍과 asyncio
는 I/O 바운드 작업(예: 네트워크 요청, 파일 읽기/쓰기)을 효율적으로 처리하기 위해 제공되는 기능입니다. 이 기능은 CPU를 기다리는 작업에서 유휴 상태로 두는 대신 다른 작업을 실행하도록 설계되어 있습니다. 아래에서 asyncio
와 관련된 핵심 개념, 동작 원리 및 사용 방법을 자세히 설명하겠습니다.
1. 비동기 프로그래밍의 기본 개념
비동기 프로그래밍은 동시에 여러 작업을 처리하는 방법입니다. 그러나 이는 멀티스레딩이나 멀티프로세싱과 다릅니다. 비동기 프로그래밍은 한 번에 하나의 작업만 실행하지만, 특정 작업이 완료될 때까지 기다리는 동안 다른 작업으로 전환할 수 있습니다.
- 동기 프로그래밍: 작업이 순차적으로 실행. 하나의 작업이 끝날 때까지 다른 작업 대기.
- 비동기 프로그래밍: 작업이 블로킹되지 않고, 작업 중간에 다른 작업이 실행될 수 있음.
2. asyncio
란?
asyncio
는 파이썬 3.3에 도입된 라이브러리로, 비동기 I/O 및 동시성 작업을 관리하는 데 사용됩니다. 주요 특징은 다음과 같습니다:
- 이벤트 루프 기반으로 작동
- 비동기 코루틴(
async def
)과 태스크(Task
) 관리 - 네트워크, 파일 I/O, 타이머 작업 처리
3. 핵심 구성 요소
1) 코루틴(Coroutine)
async def
로 정의된 함수는 코루틴입니다.- 코루틴은 실행을 일시 중단하고 이벤트 루프에 제어권을 반환할 수 있습니다.
async def example_coroutine(): print("Start coroutine") await asyncio.sleep(1) # 실행을 일시 중단 print("End coroutine")
2) await
await
는 다른 비동기 함수를 호출할 때 사용됩니다.await
은 제어권을 이벤트 루프에 넘기고, 호출된 작업이 완료되길 기다립니다.async def main(): print("Start") await asyncio.sleep(2) # 2초 대기 print("End")
3) 이벤트 루프(Event Loop)
- 이벤트 루프는 코루틴을 실행하고, 태스크를 스케줄링하며, 대기 중인 작업을 관리합니다.
asyncio.run()
은 이벤트 루프를 생성하고 실행합니다.import asyncio async def main(): print("Hello") await asyncio.sleep(1) print("World") asyncio.run(main()) # 이벤트 루프 실행
4) 태스크(Task)
- 태스크는 코루틴의 실행을 관리하는 객체입니다.
- 여러 코루틴을 동시에 실행하려면
asyncio.create_task()
를 사용합니다. async def task1(): await asyncio.sleep(1) print("Task 1 complete") async def task2(): await asyncio.sleep(2) print("Task 2 complete") async def main(): t1 = asyncio.create_task(task1()) t2 = asyncio.create_task(task2()) await t1 # 태스크 1 대기 await t2 # 태스크 2 대기 asyncio.run(main())
5) Future와 Task
- Future는 비동기 작업의 결과를 나타내는 객체입니다.
- Task는 코루틴을 실행하는 래퍼로, 내부적으로 Future를 사용합니다.
4. 주요 함수 및 메서드
1) asyncio.run(coroutine)
- 비동기 프로그램의 시작점. 이벤트 루프를 실행.
- 종료 시 루프를 닫음.
2) asyncio.create_task(coroutine)
- 코루틴을 태스크로 변환하여 이벤트 루프에 등록.
3) asyncio.gather(*coroutines)
- 여러 코루틴을 동시에 실행하고 결과를 반환.
async def main(): results = await asyncio.gather(task1(), task2()) print(results)
4) asyncio.sleep(seconds)
- 비동기적으로 대기.
5) asyncio.TimeoutError
- 일정 시간 내 작업이 완료되지 않을 경우 발생하는 예외.
5. 비동기 프로그래밍의 장점
- 효율적인 자원 사용: 비동기 작업 중에 CPU를 활용할 수 있음.
- 높은 처리량: I/O 바운드 작업을 병렬적으로 처리 가능.
- 간결한 코드: 콜백 기반의 비동기 작업보다 이해하기 쉬움.
6. 실전 예제: 웹 요청 처리
다음은 aiohttp
를 사용하여 여러 웹 페이지를 동시에 요청하는 예제입니다.
import asyncio
import aiohttp
async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
async def main():
urls = ["https://example.com", "https://python.org", "https://github.com"]
tasks = [asyncio.create_task(fetch(url)) for url in urls]
results = await asyncio.gather(*tasks)
print(results)
asyncio.run(main())
7. 주의 사항
- I/O 바운드 작업에서만 유리하며, CPU 바운드 작업에는 비효율적일 수 있음.
- 이벤트 루프는 단일 스레드에서 실행되므로, 멀티스레딩/멀티프로세싱과는 다름.
- 동기 코드와 혼합하면 프로그램의 성능이 저하될 수 있음.
asyncio
는 비동기 프로그래밍의 복잡성을 크게 줄여주는 강력한 도구입니다. 네트워크 요청, 파일 입출력, 타이머와 같은 작업에서 효율성을 높이는 데 매우 유용하니, 실제 사용 사례를 기반으로 익혀보는 것을 추천합니다.
반응형
'🖥️ IT, 컴퓨터 > 🐍 Python' 카테고리의 다른 글
[Python] HTML에서 특정 클래스 뒤에 있는 텍스트만 추출하기 (BeautifulSoup) (0) | 2024.04.25 |
---|---|
[Mecab] 일본어 형태소 분석하기 :: Mecab (0) | 2024.04.03 |
[Python] 파이썬에서 환경변수 설정하기 :: os.environ (0) | 2024.03.05 |
[Python] pd.read_csv 에서 인코딩 설정하는 법 / UnicodeDecodeError (0) | 2024.02.29 |
[Python] Plotly로 히스토그램 그래프 그리기 :: px.histogram (0) | 2024.02.03 |
댓글