파이썬은 기본적으로 동기 방식으로 동작하는 언어이지만, 파이썬 3.4에서 asyncio가 표준 라이브러리로 추가되고,
파이썬 3.5에서부터는 async/await 키워드가 문법으로 채택이 되면서, 파이썬도 이제 언어 자체적으로 비동기 프로그래밍이 가능해 졌다.
예를 들어, 다음과 같이 선언된 함수는 동기 함수입니다.
기존 def 키워드 앞에 async 키워드까지 붙이면 이 함수는 비동기 처리되며, 이러한 비동기 함수를 파이썬에서는 코루틴(coroutine)이라고도 부릅니다.
async def do_async ( ) : pass
이러한 비동기 함수는 일반 동기 함수가 호출하듯이 호출하면 coroutine 객체가 리턴됩니다.
do_async( ) # <coroutine object do_async at 0x1038de710>
따라서 비동기 함수는 일반적으로 async로 선언된 다른 비동기 함수 내에서 await 키워드를 붙여서 호출해야 합니다.
async def main_async ( ) : await do_async( )
async로 선언되지 않은 일반 동기 함수 내에서 비동기 함수를 호출하려면 asyncio 라이브러리의 이벤트 루프를 이용해야합니다.
loop = asyncio. get_event_loop( ) loop. run_until_complete( main_async( ) ) loop. close( )
파이썬 3.7 이상에서는 다음과 같이 한 줄로 간단히 비동기 함수를 호출 할 수도 있습니다.
asyncio. run( main_async( ) )
실제 저의 프로그램에 구현하기(goldstock 프로그램 일부 발췌)
import asyncioclass Kiwoom(QAxWidget): def __init__ (self ): super ().__init__ () self .ui = SetupUI() self .realType = RealType() self .logging = Logging() self .slack = Slack() # 슬랙 동작 #중간생략... def auto_AI_recommend_clicked (self ): now = datetime.now() if self .ui.btnCdtResult_buy.isChecked(): self .ai_recommend_timer_start() else : self .timer_ai_recommend.stop() return def ai_recommend_timer_start (self ): self .timer_ai_recommend = QTimer() self .timer_ai_recommend.start(5 * 1000 ) # 5 초 간격으로 self .timer_ai_recommend.timeout.connect(self .ai_recommend_click) def ai_recommend_click (self ): market_status, decision_list = self .decide_to_autoTrading(stockCode) if market_status == " 매수 " or market_status == " 강력매수 " : if self .ui.btnAutotrade.isChecked(): asyncio .run(self .decide_to_sell(1 , stockCode)) asyncio .run(self .decide_to_sell(2 , balance_detail_stockCode)) else : if (market_status == " 매도 " or market_status == " 강력매도 " ) and stockCode in self .account_stock_dict: if self .ui.btnAutotrade.isChecked(): asyncio .run(self .decide_to_sell(1 , stockCode)) asyncio .run(self .decide_to_sell(2 , balance_detail_stockCode)) async def decide_to_sell (self , num , stockCode): day_chart_data = {} minute_chart_data = {} week_chart_data = {} month_chart_data = {} recommInterval = str (self .ui.cbRecommInterval.currentText().replace(' ' , '' )) minute_chart_interval = str (self .ui.spinBox_minutes.value()) market_status, decision_list = self .decide_to_autoTrading_condtion2(stockCode =stockCode) if market_status in (" 매도 " , " 강력매도 " ): self .time_to_trading(order_currency =stockCode, type =" 매도 " , market_status =" 매도 " , \ current_price =current_price, target_time =recommInterval, date =order_date, real_flag ="R" , \ decision_list =decision_list) elif market_status in (" 매수 " , " 강력매수 " ): self .time_to_trading(order_currency =stockCode, type =" 매수 " , market_status =" 매수 " , \ current_price =current_price, target_time =recommInterval, date =order_date, real_flag ="R" , \ decision_list =decision_list) else : # 관망 pass def time_to_trading (self , order_currency="" , type="" , market_status="" , target_units=0 , current_price=0 , \ target_time="" , date="" , real_flag="" , decision_list="" ): if type in (" 매도 " , " 강력매도 " ): # 매도 try : self .sendOrder(" 신규매도 " , order_currency, " 시장가 " , int (possible_quantity), int (current_price)) except (ParameterTypeError, KiwoomProcessingError) as e: self .showDialog('Critical' , e) return self .slack.notification(\ pretext ="%s(%s) 시장가 매도주문 완료 ( 로직 No:%s)" % (stockName, order_currency, str_decision_list), title ="%s 주문수량 : %s 현재가 : %s" % (self .now.strftime("%Y-%m-%d %H:%M:%S" ), possible_quantity, \ current_price), text ="https://finance.daum.net/chart/A%s " % order_currency) else: # 매수주문 try : self .ui.pteLog.appendPlainText("%s(%s) ( 신규매수 , 시장가 ) 주문전송 " % (stockName, order_currency)) self .logging.logger.debug("%s(%s) ( 신규매수 , 시장가 ) 주문전송 " % (stockName, order_currency)) self .sendOrder(" 신규매수 " , order_currency, " 시장가 " , int (target_units), int (current_price)) except (ParameterTypeError , KiwoomProcessingError) as e: self .showDialog( 'Critical' , e) self .ui.pteLog.appendPlainText( "%s(%s) 매수주문 오류발생 " % (stockName , order_currency)) self .logging.logger.debug( "%s(%s) 매수주문 오류발생 " % (stockName , order_currency)) return # 거래내역 DB저장 self .insert_db_transaction_infos(self .not_account_stock_dict[self .orderNo]) # result
이 프로그램에 실제 구현하여 동시성 병렬프로그램 함수 처리속도가 배가 빨라졌습니다.
이 기능에 대한 설명은 하기 사이트를 참조하였습니다. 감사합니다.
https://www.daleseo.com/python-asyncio/
[파이썬] asyncio로 비동기 처리하기
Engineering Blog by Dale Seo
www.daleseo.com