본문으로 건너뛰기

Async로 for문과 while문

for 문과 while문 여러개를 동시에 돌리고 싶어져서 좀 알아보았다.

파이썬 3.4에서 asyncio가 표준 라이브러리로 추가되고,
파이썬 3.5에서 async/await 키워드가 문법으로 채택이 되면서,
파이썬도 이제 언어 자체적으로 비동기 프로그래밍이 가능 해졌다고 한다.

자바스크립트와 비슷하다 -_-;;

메서드 앞에 async 를 붙힘으로써 비동기 메서드로써 사용 가능하다.

def example():
...

이런식으로 말이다.

async def example():
...

비동기 함수를 보통 함수처럼 호줄하면 안된다 이렇게 coroutine 객체가 리턴되버린다

example() # <coroutine object do_async at 0x1038de710>

비동기 함수는 일반적으로 async로 선언된 다른 비동기 함수 내에서
await 키워드를 붙여서 호출해야 한다.


async로 선언되지 않은 일반 동기 함수 내에서 비동기 함수를 호출하려면
asyncio 라이브러리의 이벤트 루프를 이용하면 된다.

loop = asyncio.get_event_loop()
loop.run_until_complete(main_async())
loop.close()

파이썬 3.7이상에서는 한줄로 간단히 비동기 함수를 호출 할 수 있다.

asyncio.run(main_async())

일반적인 for문 2개

예제코드로 보자.

먼저 일반적임 동기식 코드이다

def first_for():
for i in range(1, 5):
print("first_for / " + "i = {}".format(i))
time.sleep(1)


def second_for():
for i in range(1, 5):
print("second_for / " + "i = {}".format(i))
time.sleep(1)

def main_process():
start = time.time()

first_for()
second_for()

end = time.time()
print("소요시간 : {}".format(end - start))

if __name__ == '__main__':
main_process()
first_for / i = 1
first_for / i = 2
first_for / i = 3
first_for / i = 4
second_for / i = 1
second_for / i = 2
second_for / i = 3
second_for / i = 4
소요시간 : 8.008337259292603

비동기식으로 for문을 동시에 2개 돌림

위의 코드를 비동기식으로 바꿔봤다.
동시에 for문을 돌리고 싶어서 이다.

async def first_for():
for i in range(1, 5):
print("first_for / " + "i = {}".format(i))
await asyncio.sleep(1) # 비동기 슬립


async def second_for():
for i in range(1, 5):
print("second_for / " + "i = {}".format(i))
await asyncio.sleep(1) # 비동기 슬립

async def main_process():
start = time.time()

# 비동기 실행 (이렇게 쓰는 방식은 deprecated됨)
# await asyncio.wait([
# first_for(),
# second_for()
#
# ])
await asyncio.wait([
asyncio.create_task(first_for()),
asyncio.create_task(second_for())
])

end = time.time()
print("소요시간 : {}".format(end - start))

if __name__ == '__main__':
asyncio.run(main_process())
first_for / i = 1
second_for / i = 1
first_for / i = 2
second_for / i = 2
first_for / i = 3
second_for / i = 3
first_for / i = 4
second_for / i = 4
소요시간 : 4.004305362701416

이부분이 deprecated 되어서 요즘 사용하는 방식으로 수정했다.

await asyncio.wait([
first_for(),
second_for()
])

비동기식 while (무한루프)

경우에 따라서는 while 문을 비동기로 여러개 돌려야 할수도 있으므로..
사실 이것때문에 자료를 찾아봄 ㅋㅋ

async def first_while():
while True:
print("first_while")
await asyncio.sleep(1) # 비동기 슬립

async def second_while():
while True:
print("second_while")
await asyncio.sleep(1) # 비동기 슬립

async def main_process():
start = time.time()

# 비동기 실행 (이렇게 쓰는 방식은 deprecated됨)
# await asyncio.wait([
# first_for(),
# second_for()
#
# ])
await asyncio.wait([
asyncio.create_task(first_while()),
asyncio.create_task(second_while())
])

end = time.time()
print("소요시간 : {}".format(end - start))

if __name__ == '__main__':
asyncio.run(main_process())
first_while
second_while
first_while
second_while
first_while
second_while
.
.
.
.

조건식을 넣은 while 비동기

async def first_while():
i = 0
while True:
print("first_while / i = {}".format(i))
i += 1
if i == 10:
break
await asyncio.sleep(1) # 비동기 슬립

async def second_while():
i = 0
while True:
print("second_while / i = {}".format(i))
i += 1
if i == 10:
break
await asyncio.sleep(1) # 비동기 슬립

async def main_process():
start = time.time()

# 비동기 실행 (이렇게 쓰는 방식은 deprecated됨)
# await asyncio.wait([
# first_for(),
# second_for()
#
# ])
await asyncio.wait([
asyncio.create_task(first_while()),
asyncio.create_task(second_while())
])

end = time.time()
print("소요시간 : {}".format(end - start))

if __name__ == '__main__':
asyncio.run(main_process())
first_while / i = 0
second_while / i = 0
first_while / i = 1
second_while / i = 1
first_while / i = 2
second_while / i = 2
first_while / i = 3
second_while / i = 3
first_while / i = 4
second_while / i = 4
first_while / i = 5
second_while / i = 5
first_while / i = 6
second_while / i = 6
first_while / i = 7
second_while / i = 7
first_while / i = 8
second_while / i = 8
first_while / i = 9
second_while / i = 9
소요시간 : 9.00925898551941

Process finished with exit code 0


조금 다른스타일의 조건식 비동기 while

async def first_while():
i = 10
while i > 0:
print("first_while / i = {}".format(i))
i -= 1
await asyncio.sleep(1) # 비동기 슬립

async def second_while():
i = 10
while i > 0:
print("second_while / i = {}".format(i))
i -= 1
await asyncio.sleep(1) # 비동기 슬립

async def main_process():
start = time.time()

# 비동기 실행 (이렇게 쓰는 방식은 deprecated됨)
# await asyncio.wait([
# first_for(),
# second_for()
#
# ])
await asyncio.wait([
asyncio.create_task(first_while()),
asyncio.create_task(second_while())
])

end = time.time()
print("소요시간 : {}".format(end - start))

if __name__ == '__main__':
asyncio.run(main_process())
first_while / i = 10
second_while / i = 10
first_while / i = 9
second_while / i = 9
first_while / i = 8
second_while / i = 8
first_while / i = 7
second_while / i = 7
first_while / i = 6
second_while / i = 6
first_while / i = 5
second_while / i = 5
first_while / i = 4
second_while / i = 4
first_while / i = 3
second_while / i = 3
first_while / i = 2
second_while / i = 2
first_while / i = 1
second_while / i = 1
소요시간 : 10.011247396469116

Process finished with exit code 0