"프로그래밍 언어의 개념과 흐름에 대한 고찰 - 파이썬답게 코딩하기" 학습중...


비동기 기법에 대해 알아보는데 처음 보는 생소한 개념이라 이해하는데 어려움이 좀 있네요.



## Python 3.2버젼 비동기 논블록 구현시 콜백 함수 사용. 예외처리나 디버깅에 어려움
## Python 3.3 yield from이 등장.
## Python 3.4 Asyncio 추가

# import asyncio
# import random
# import datetime
#
# @asyncio.coroutine ## 데코레이터로 구현된 코루틴.
# def print_time(idx) :
# sleep_time = random.randrange(1, 10)
# print(sleep_time)
# yield from asyncio.sleep(sleep_time)
# print("[%s] sleep time : %s, complete time : %s" % (idx, sleep_time, datetime.datetime.now()))
#
# def main() :
# futures = [print_time(i) for i in range(10)]
# loop = asyncio.get_event_loop()
# loop.run_until_complete(asyncio.wait(futures))
# loop.close()
#
# if __name__ == "__main__" :
# main()



(실행 결과)


# 4
# 5
# 4
# 8
# 8
# 2
# 5
# 7
# 3
# 2
# [5] sleep time : 2, complete time : 2020-08-30 18:50:31.073389
# [1] sleep time : 2, complete time : 2020-08-30 18:50:31.104254
# [7] sleep time : 3, complete time : 2020-08-30 18:50:32.100427
# [8] sleep time : 4, complete time : 2020-08-30 18:50:33.094911
# [9] sleep time : 4, complete time : 2020-08-30 18:50:33.095925
# [6] sleep time : 5, complete time : 2020-08-30 18:50:34.087446
# [2] sleep time : 5, complete time : 2020-08-30 18:50:34.087446
# [0] sleep time : 7, complete time : 2020-08-30 18:50:36.086021
# [3] sleep time : 8, complete time : 2020-08-30 18:50:37.095603
# [4] sleep time : 8, complete time : 2020-08-30 18:50:37.096612




## Asyncio in Python 3.5
## async await 문법 추가. async = @asyncio.coroutine, await = yield from

# import asyncio
# import random
# import datetime
#
# async def print_time(idx) :
# sleep_time = random.randrange(1, 10)
# print(sleep_time)
# await asyncio.sleep(sleep_time)
# print("[%s] sleep time : %s, complete time : %s" % (idx, sleep_time, datetime.datetime.now()))
#
# def main() :
# futures = [print_time(i) for i in range(10)]
# loop = asyncio.get_event_loop()
# loop.run_until_complete(asyncio.wait(futures))
# loop.close()
#
# if __name__ == "__main__" :
# main()



(실행 결과)


# 5
# 4
# 4
# 9
# 5
# 6
# 5
# 3
# 9
# 9
# [0] sleep time : 3, complete time : 2020-08-30 19:02:12.860910
# [9] sleep time : 4, complete time : 2020-08-30 19:02:13.848743
# [2] sleep time : 4, complete time : 2020-08-30 19:02:13.848743
# [6] sleep time : 5, complete time : 2020-08-30 19:02:14.853861
# [3] sleep time : 5, complete time : 2020-08-30 19:02:14.853861
# [8] sleep time : 5, complete time : 2020-08-30 19:02:14.854858
# [5] sleep time : 6, complete time : 2020-08-30 19:02:15.847032
# [4] sleep time : 9, complete time : 2020-08-30 19:02:18.858229
# [7] sleep time : 9, complete time : 2020-08-30 19:02:18.859240
# [1] sleep time : 9, complete time : 2020-08-30 19:02:18.861211




# import asyncio
#
# class AsynchronousReader :
# def __init__(self, file_name):
# self.file_name = file_name
# self.file = None
#
# try :
# self.file = open(self.file_name, "rb")
# except :
# print("file open error")
#
# def __aiter__(self):
# return self
#
# async def __anext__(self):
# value = await self.file_readline()
# if value == b"":
# raise StopAsyncIteration
# return value.decode("utf-8").strip()
#
# async def file_readline(self):
# return self.file.readline()
#
# def file_close(self) :
# self.file.close()
#
# async def read_file(file_name) :
# async_reader = AsynchronousReader(file_name)
# async for value in async_reader:
# print(value)
# async_reader.file_close()
#
# if __name__ =="__main__" :
# loop = asyncio.get_event_loop()
# try :
# loop.run_until_complete(read_file("./python_foundation_mission_statement"))
# finally :
# loop.close()



(실행 결과)


# the mission of the python software foundation is to promote, protect,
# and advance the python programming language, and to support and
# facilitate the growth of a diverse and international community of
# python programmers.
#
# from the mission statement page




# import asyncio
#
# class AsynchronousReader :
# def __init__(self, file_name):
# self.file_name = file_name
# self.file = None
#
# async def __aenter__(self):
# try :
# self.file = open(self.file_name, "rb")
# except :
# print("file open error")
# raise Exception
# else:
# return self.file
#
# async def __aexit__(self, exc_type, exc_value, traceback):
# self.file.close()
#
# async def read_file(file_name) :
# async with AsynchronousReader(file_name) as af:
# for line in af.readlines() :
# print(line.decode("utf-8").strip())
#
# if __name__ == "__main__" :
# loop = asyncio.get_event_loop()
# try :
# loop.run_until_complete(read_file("./python_foundation_mission_statement"))
# finally :
# loop.close()



(실행 결과)


# the mission of the python software foundation is to promote, protect,
# and advance the python programming language, and to support and
# facilitate the growth of a diverse and international community of
# python programmers.
#
# from the mission statement page




## Asyncio in Python 3.6
## native 코루틴 안에서도 yield yield from 사용하도록 개선.이로써 native 코루틴으로 generator를 만들 수 있음.

# import asyncio
#
# async def delay_range(to, delay = 1) :
# for i in range(to) :
# yield i
# await asyncio.sleep(delay)
#
# async def run() :
# async for i in delay_range(10) :
# print(i)
#
# if __name__ =="__main__" :
# loop = asyncio.get_event_loop()
# try :
# loop.run_until_complete(run())
# finally :
# loop.close()



(실행 결과)


# 0
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9




# import asyncio
#
# async def delay_range(to, delay = 1) :
# for i in range(to) :
# yield i
# await asyncio.sleep(delay)
#
# async def run() :
# print("async comprehension")
# return [i async for i in delay_range(3)]
#
# async def run_multiple() :
# print("async await comprehension")
# func_list = [run, run]
# result = [await func() for func in func_list]
# print(result)
#
# if __name__ =="__main__" :
# loop = asyncio.get_event_loop()
# try :
# loop.run_until_complete(run_multiple())
# finally :
# loop.close()



(실행 결과)


# async await comprehension
# async comprehension
# async comprehension
# [[0, 1, 2], [0, 1, 2]]




## Asyncio in Python 3.7, 3.8
## asyncio를 이해하는데 필요한 세가지 개념
## event loop, future, task
## event loop - 대부분의 비동기 로직에는 각자의 event loop가 있다. 비동기 함수를 예약해서 작업 관리
## future - concurrents.futures와 같은 역할.asyncio에서는 작업관리를 task기반으로 한다.future는 향후 작업을 의미.

# import asyncio
# import datetime
#
# async def func(caller) :
# print("start %s" % caller)
# await asyncio.sleep(3)
# print("end %s" % caller)
# return "done"
#
# async def coro() :
# c = func("coro")
# print(c)
# print(dir(c))
# ret = await c
# print("coro ret : %s" % ret)
#
# async def task() :
# t = asyncio.ensure_future(func("task"))
# print(t)
# print(dir(t))
# ret = await t
# print("task ret : %s" % ret)
#
# def callback(future) :
# print("task callback")
#
# def main() :
# loop = asyncio.get_event_loop()
# loop.run_until_complete(coro())
# loop.run_until_complete(task())
# loop.close()
#
# if __name__ =="__main__" :
# main()



(실행 결과)


# <coroutine object func at 0x0000026A9C8AF6D0>
# ['__await__', '__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',
# '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '
# __le__', '__lt__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__',
# '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'cr_await', 'cr_code', 'cr_frame', 'cr_running',
# 'send', 'throw']
# start coro
# end coro
# coro ret : done
# <Task pending coro=<func() running at C:/PythonProject/autobuy/test4.py:246>>
# ['__await__', '__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',
# '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '
# __iter__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
# '__sizeof__', '__str__', '__subclasshook__', '_asyncio_future_blocking', '_callbacks', '_coro', '_exception',
# '_fut_waiter', '_log_destroy_pending', '_log_traceback', '_loop', '_must_cancel', '_repr_info', '_result',
# '_schedule_callbacks', '_source_traceback', '_state', '_step', '_wakeup', 'add_done_callback', 'all_tasks',
# 'cancel', 'cancelled', 'current_task', 'done', 'exception', 'get_stack', 'print_stack', 'remove_done_callback',
# 'result', 'set_exception', 'set_result']
# start task
# end task
# task ret : done




# import asyncio
# import random
# import datetime
#
# async def print_time(idx) :
# sleep_time = random.randrange(1, 5)
# print(sleep_time)
# await asyncio.sleep(sleep_time)
# print("[%s] sleep time : %s, complete time : %s" % (idx, sleep_time, datetime.datetime.now()))
# return idx
#
# async def tasks() :
# task_list = [asyncio.ensure_future(print_time(i)) for i in range(10)]
# for idx, task in enumerate(task_list) :
# if idx % 2 == 0 :
# task.cancel()
# print("[%s] task is cancelled" % idx)
# else :
# task.add_done_callback(callback)
# await asyncio.wait(task_list)
#
# def callback(task) :
# print("[%s] call callback func" % task.result())
#
# def main() :
# loop = asyncio.get_event_loop()
# loop.run_until_complete(tasks())
# loop.close()
#
# if __name__ == "__main__" :
# main()



(실행 결과)


# [0] task is cancelled
# [2] task is cancelled
# [4] task is cancelled
# [6] task is cancelled
# [8] task is cancelled
# 4
# 2
# 4
# 2
# 3
# [3] sleep time : 2, complete time : 2020-08-30 21:08:59.506249
# [7] sleep time : 2, complete time : 2020-08-30 21:08:59.507242
# [3] call callback func
# [7] call callback func
# [9] sleep time : 3, complete time : 2020-08-30 21:09:00.495617
# [9] call callback func
# [1] sleep time : 4, complete time : 2020-08-30 21:09:01.505610
# [5] sleep time : 4, complete time : 2020-08-30 21:09:01.506629
# [1] call callback func
# [5] call callback func




## 그외 파이선 모듈
## greenlet - 경량화된 코루틴 라이브러리
## Twisted - 웹 서버용 이벤트 중심의 네트워킹 엔진
## Tornado - 빠른 응답성이 장점.
## PP - Parellel Python의 약자. 비동기적 처리는 아니나 병렬성을 활용하여 작업 효율성을 높인다.
# import greenlet
#
# def worker1() :
# print("enter the work1 funcion")
# gr2.switch()
# print("exit the work1 function")
#
# def worker2() :
# print("enter the work1 funcion")
# gr1.switch()
# print("exit the work1 function")
#
# if __name__ == "__main__" :
# gr1 = greenlet.greenlet(worker1)
# gr2 = greenlet.greenlet(worker2)
# gr1.switch()



(실행 결과)


# enter the work1 funcion
# enter the work1 funcion
# exit the work1 function




# import random
# import gevent
#
# def worker(index) :
# print("[%s] enter the work function" % index)
# gevent.sleep(random.randrange(1,5))
# print("[%s] exit the work function" % index)
#
# if __name__ == "__main__" :
# workers = [gevent.spawn(worker, i) for i in range(10)]
# gevent.joinall(workers)



(실행 결과)


# [0] enter the work function
# [1] enter the work function
# [2] enter the work function
# [3] enter the work function
# [4] enter the work function
# [5] enter the work function
# [6] enter the work function
# [7] enter the work function
# [8] enter the work function
# [9] enter the work function
# [5] exit the work function
# [7] exit the work function
# [1] exit the work function
# [6] exit the work function
# [8] exit the work function
# [9] exit the work function
# [0] exit the work function
# [2] exit the work function
# [3] exit the work function
# [4] exit the work function



+ Recent posts