์ฃผ์ ๊ฐ๋
ํ์ด์ฌ์ asyncio ๋ชจ๋์ ๋น๋๊ธฐ I/O, ์ด๋ฒคํธ ๋ฃจํ, coroutines ๋ฐ ํ์คํฌ(task) ๊ด๋ฆฌ ๋ฑ์ ํตํด ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ์ง์ํ๋ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. asyncio๋ฅผ ์ฌ์ฉํ๋ฉด ๋คํธ์ํฌ ๋ฐ ์น ์์ผ, ๋ฐ์ดํฐ๋ฒ ์ด์ค, ํ์ผ I/O ๋ฑ์ ์์ ์ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
- ์ด๋ฒคํธ ๋ฃจํ (Event Loop):
- ์ด๋ฒคํธ ๋ฃจํ๋ ์ฝ๋ฃจํด๊ณผ ์ฝ๋ฐฑ์ ๊ด๋ฆฌํ๊ณ , I/O ์์ ์ด ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๋ ์ญํ ์ ํฉ๋๋ค.
- asyncio.run() ํจ์๋ฅผ ํตํด ์ด๋ฒคํธ ๋ฃจํ๋ฅผ ์์ํ ์ ์์ต๋๋ค.
- ์ฝ๋ฃจํด (Coroutine):
- async def๋ก ์ ์๋ ํจ์์ ๋๋ค.
- await ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ค๋ฅธ ์ฝ๋ฃจํด์ด๋ ๋น๋๊ธฐ ์์ ์ ๊ธฐ๋ค๋ฆฝ๋๋ค.
- ํ์คํฌ (Task):
- ์ฝ๋ฃจํด์ ์ด๋ฒคํธ ๋ฃจํ์์ ์คํํ ์ ์๋ ๋จ์๋ก ๋ณํํฉ๋๋ค.
- asyncio.create_task()๋ฅผ ์ฌ์ฉํ์ฌ ํ์คํฌ๋ฅผ ์์ฑํ๊ณ , ์ด๋ฅผ ํตํด ์ฌ๋ฌ ์ฝ๋ฃจํด์ ๋์์ ์คํํ ์ ์์ต๋๋ค.
- ํจ์ฒ (Future):
- ๋น๋๊ธฐ ์ฐ์ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ํ๋ ๋๋ค.
- ์ฝ๋ฃจํด์ด๋ ํ์คํฌ์ ๊ฒฐ๊ณผ๋ฅผ ํํํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
์ฃผ์ ํจ์ ๋ฐ ์ฌ์ฉ๋ฒ
์ด๋ฒคํธ ๋ฃจํ ์คํ
import asyncio
async def main():
print("Hello, asyncio!")
# ์ด๋ฒคํธ ๋ฃจํ ์คํ
asyncio.run(main())
์ฝ๋ฃจํด ์ ์ ๋ฐ ์คํ
import asyncio
async def say_hello():
print("Hello!")
await asyncio.sleep(1)
print("Goodbye!")
async def main():
await say_hello()
asyncio.run(main())
ํ์คํฌ ์์ฑ ๋ฐ ์คํ
import asyncio
async def say_after(delay, message):
await asyncio.sleep(delay)
print(message)
async def main():
task1 = asyncio.create_task(say_after(1, "Hello"))
task2 = asyncio.create_task(say_after(2, "World"))
await task1
await task2
asyncio.run(main())
๊ณ ๊ธ ๊ธฐ๋ฅ
์ฌ๋ฌ ํ์คํฌ ๋์์ ์คํ
import asyncio
async def say_hello():
await asyncio.sleep(1)
print("Hello!")
async def say_goodbye():
await asyncio.sleep(2)
print("Goodbye!")
async def main():
await asyncio.gather(say_hello(), say_goodbye())
asyncio.run(main())
ํ์์์ ์ค์
import asyncio
async def long_running_task():
await asyncio.sleep(5)
return "Completed"
async def main():
try:
result = await asyncio.wait_for(long_running_task(), timeout=3)
print(result)
except asyncio.TimeoutError:
print("Task timed out")
asyncio.run(main())
๋น๋๊ธฐ I/O ์์
import asyncio
async def read_file(file_path):
loop = asyncio.get_event_loop()
with open(file_path, 'r') as file:
data = await loop.run_in_executor(None, file.read)
return data
async def main():
content = await read_file('example.txt')
print(content)
asyncio.run(main())
์์ฝ
asyncio๋ ํ์ด์ฌ์์ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ์ฝ๊ฒ ๊ตฌํํ ์ ์๋๋ก ๋ค์ํ ๋๊ตฌ์ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ์ด๋ฒคํธ ๋ฃจํ๋ฅผ ํตํด ์ฝ๋ฃจํด๊ณผ ํ์คํฌ๋ฅผ ๊ด๋ฆฌํ๊ณ , ๋คํธ์ํฌ์ ํ์ผ I/O ๊ฐ์ ๋น๋๊ธฐ ์์ ์ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ์๋ต์ฑ์ด ๋๊ณ ์์์ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ๋ ํ๋ก๊ทธ๋จ์ ์์ฑํ ์ ์์ต๋๋ค.
โ๏ธ์ฌ๊ธฐ๊น์ง๊ฐ ์น ํ์ด์ง ๋ฐ GPT์ ๋์์ ๋ฐ์ ํฌ์คํ ์ ๋๋ค.
โ๏ธ ์ฌ๊ธฐ๋ถํฐ๋ ๊ฐ์๋ฅผ ํตํด ํ์ตํ ๋ด์ฉ ์ ๋ฆฌ์ ๋๋ค.
๊ฐ์
import asyncio
import time
async def sleep():
await asyncio.sleep(1)
async def sum(name, numbers):
start = time.time()
total = 0
for number in numbers:
await sleep()
total += number
print(f'์์
์ค={name}, number={number}, total={total}')
end = time.time()
print(f'์์
๋ช
={name}, ๊ฑธ๋ฆฐ์๊ฐ={end-start}')
return total
async def main():
start = time.time()
task1 = asyncio.create_task(sum("A", [1, 2]))
task2 = asyncio.create_task(sum("B", [1, 2, 3]))
await task1
await task2
result1 = task1.result()
result2 = task2.result()
end = time.time()
print(f'์ดํฉ={result1+result2}, ์ด์๊ฐ={end-start}')
if __name__ == "__main__":
asyncio.run(main())
ํจ์๋ฅผ ๋น๋๊ธฐ๋ก ํธ์ถํ๋ ค๋ฉด ์ด๋ ๊ฒ def ์์ async๋ผ๋ ํค์๋๋ฅผ ๋ฃ์ผ๋ฉด ๋๋ค. ๊ทธ๋ฌ๋ฉด ์ด์ ์ด ํจ์๋ ๋น๋๊ธฐ ํจ์๊ฐ ๋๋ค. ์ด๋ async๋ฅผ ์ ์ฉํ ๋น๋๊ธฐ ํจ์๋ฅผ ์ฝ๋ฃจํด์ด๋ผ ๋ถ๋ฅธ๋ค.
๋ํ, ์ฝ๋ฃจํด ์์์ ๋ค๋ฅธ ์ฝ๋ฃจํด์ ํธ์ถํ ๋๋ await sleep()๊ณผ ๊ฐ์ด await๋ฅผ ํจ์๋ช ์์ ๋ถ์ฌ ํธ์ถํด์ผ ํ๋ค. ์ฝ๋ฃจํด ์ํ ์ค await ์ฝ๋ฃจํด์ ๋ง๋๋ฉด await๋ก ํธ์ถํ ์ฝ๋ฃจํด์ด ์ข ๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ์ ์ด๊ถ์ ๋ฉ์ธ ์ค๋ ๋๋ ๋ค๋ฅธ ์ฝ๋ฃจํด์ผ๋ก ๋๊ธด๋ค. ์ด๋ฌํ ๋ฐฉ์์ ๋๋ธ๋กํน(non-blocking)์ด๋ผ ํ๋ค. ๊ทธ๋ฆฌ๊ณ ํธ์ถํ ์ฝ๋ฃจํด์ด ์ข ๋ฃ๋๋ฉด ์ด๋ฒคํธ์ ์ํด ๋ค์ ๊ทธ ์ดํ ์์ ์ด ์ํ๋๋ค.
์ฌ๊ธฐ์ ํ๋ ๋์ฌ๊ฒจ๋ด์ผ ํ ์ ์ sleep() ํจ์์์ time.sleep(1) ๋์ asyncio.sleep(1)๋ฅผ ์ฌ์ฉํ ๋ถ๋ถ์ด๋ค. ์ฝ๋ฃจํด์ด ์๋ time.sleep(1)์ ์ฌ์ฉํ๋ค๋ฉด await๊ฐ ์ ์ฉ๋์ง ์์ ์คํ ์๊ฐ์ ์ค์ผ ์ ์๋ค.
main() ํจ์์์ ์ฌ์ฉํ asyncio.create_task()๋ ์ํํ ์ฝ๋ฃจํด ์์ (ํ์คํฌ)์ ์์ฑํ๋ค. ์ฌ๊ธฐ์๋ ์์ ์ ์์ฑํ ๋ฟ์ด์ง ์ค์ ๋ก ์ฝ๋ฃจํด์ด ์ํ๋๋ ๊ฒ์ ์๋๋ค. ์ค์ ์ฝ๋ฃจํด ์คํ์ await ํ์คํฌ๊ฐ ๋ด๋นํ๋ค. ๊ทธ๋ฆฌ๊ณ ์คํ ํ์คํฌ์ ๊ฒฐ๊ด๊ฐ์ ํ์คํฌ.result()๋ก ์ป์ ์ ์๋ค.
asyncio.create_task()๋ ์ฝ๋ฃจํด์ ๋์์ ์คํํ๋ ๋ฐ ๊ผญ ํ์ํ๋ค. ๋ค์์ฒ๋ผ ํ์คํฌ๊ฐ ์๋ await๋ก ์ฝ๋ฃจํด์ ์คํํ๋ค๋ฉด ์ฝ๋ฃจํด์ด ๋์์ ์คํ๋์ง ์๊ณ ํ๋์ฉ ์ฐจ๋ก๋ก ์คํ๋์ด ์ด๋์ด ์์ ๊ฒ์ด๋ค.
result1 =await sum("A", [1, 2])
result2 =await sum("B", [1, 2, 3])
asyncio.run(main())์ ๋ฐ ๋ฃจํ๋ฅผ ์์ฑํ์ฌ main() ์ฝ๋ฃจํด์ ์คํํ๋ค. ์ฝ๋ฃจํด์ ์คํํ๋ ค๋ฉด ๋ฐ ๋ฃจํ๊ฐ ๋ฐ๋์ ํ์ํ๋ค. ์ฝ๋ฃจํด์ด ๋ชจ๋ ๋น๋๊ธฐ์ ์ผ๋ก ์คํ๋๊ธฐ ๋๋ฌธ์ ๊ทธ ์์๊ณผ ์ข ๋ฃ๋ฅผ ๊ฐ์งํ ์ ์๋ ์ด๋ฒคํธ ๋ฃจํ๊ฐ ๋ฐ๋์ ํ์ํ๊ธฐ ๋๋ฌธ์ด๋ค.
์ด ์ฝ๋๋ฅผ ์คํํ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.
c:\\projects\\pylib>python asyncio_sample.py
์์
์ค=A, number=1, total=1
์์
์ค=B, number=1, total=1
์์
์ค=A, number=2, total=3
์์
๋ช
=A, ๊ฑธ๋ฆฐ์๊ฐ=2.000617742538452
์์
์ค=B, number=2, total=3
์์
์ค=B, number=3, total=6
์์
๋ช
=B, ๊ฑธ๋ฆฐ์๊ฐ=3.000927209854126
์ดํฉ=9, ์ด์๊ฐ=3.000927209854126
A ์์ ๊ณผ B ์์ ์ ๊ต๋๋ก ํธ์ถํ๋ค. (์ ์ด๊ถ์ด await์ ์ํด ๊ณ์ ๋ฐ๋๋ค๋ ๊ฒ์ ์ ์ ์๋ค.) ๊ทธ๋ฆฌ๊ณ ์๊ฐ๋ 5์ด ๊ฑธ๋ฆฌ๋ ๊ฒ์ด 3์ด๋ง ๊ฑธ๋ฆฌ๊ฒ ๋๋ฏ๋ก A, B ์์ ์ด ์์ ํ ๋น๋๊ธฐ์ ์ผ๋ก ๋์ํ๋ค๋ ๊ฒ์ ์ ์ ์๋ค.
๋น์ทํ ์์
import asyncio
import time
# Sync ํจ์
def execute_calc_sync(name, n):
for i in range(1, n+1):
print(f"{name} -> {i} of {n} is calculating...")
time.sleep(1)
print(f"{name} is done!")
def process_sync():
start = time.time()
execute_calc_sync('one', 3)
execute_calc_sync('two', 2)
execute_calc_sync('three', 1)
end = time.time()
print(f"total seconds : {end - start}")
# Async ํจ์
async def execute_calc_async(name, n):
for i in range(1, n+1):
print(f"{name} -> {i} of {n} is calculating...")
await asyncio.sleep(1)
print(f"{name} is done!")
async def process_async():
start = time.time()
await asyncio.gather(
execute_calc_async('one', 1),
execute_calc_async('two', 2),
execute_calc_async('three', 3)
)
end = time.time()
print(f"total seconds : {end - start}")
if __name__ == "__main__":
# Sync ์คํ
# process_sync()
# Async ์คํ
# ํ์ด์ฌ 3.7 ์ด์
asyncio.run(process_async())
one -> 1 of 1 is calculating...
two -> 1 of 2 is calculating...
three -> 1 of 3 is calculating...
one is done!
two -> 2 of 2 is calculating...
three -> 2 of 3 is calculating...
two is done!
three -> 3 of 3 is calculating...
three is done!
total seconds : 3.0082101821899414
Syncํจ์๋ก ์คํํ๋ฉด 6์ด๊ฐ ๊ฑธ๋ฆฐ๋ค. ์ฝ๋์์ ASync ํจ์๋ถ๋ถ์ ์ง์คํ์. main์์ asyncio.runํํ๋ก asyncํจ์๋ฅผ ํธ์ถํ๋ค. ๊ทธ๋ฆฌ๊ณ ์ฌ๋ฌ๊ฐ์ ๋น๋๊ธฐ ํจ์๋ฅผ ๋ฌถ์ด์ await์ผ๋ก ํธ์ถํ ์ ์๋ await asyncio,gather๋ฅผ ์ฌ์ฉํ๋ค.
์ฐธ๊ณ ํ ๋งํ ๋ฌธ์
071 ๋น๋๊ธฐ ๋ฐฉ์์ผ๋ก ํ๋ก๊ทธ๋๋ฐํ๋ ค๋ฉด? โ asyncio
'Python' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์ฝ๋ฃจํด (0) | 2024.06.23 |
---|---|
ํ์ด์ฌ ๊น์ ๋ณต์ฌ์ ์์ ๋ณต์ฌ (0) | 2024.04.29 |
Mutable๊ณผ Immutable ๊ฐ์ฒด (0) | 2024.04.29 |
ํ์ด์ฌ ํจํน(packing)๊ณผ ์ธํจํน(unpacking)์ ๋ชจ๋ ๊ฒ (1) | 2023.12.17 |
ํ์ด์ฌ map, filter ํจ์(with. iterator) (0) | 2023.12.17 |
๋๊ธ