[CREON PLUS API 활용] BlockRequest 와 Request

2018. 12. 11. 20:38개발/파이썬

크레온 플러스 API를 이용해서 통신하는 방법은 다음 2가지가 있습니다


  • BlockRequest 방식 - 가장 간단한 데이터 요청
  • Request 호출 후 Received 이벤트를 수신 받기 

아래 코드는 두 가지 방식으로 현재가를 통신하는 코드 입니다.
import pythoncom
from PyQt5.QtWidgets import *
import win32com.client
 
import win32event
 
g_objCodeMgr = win32com.client.Dispatch('CpUtil.CpCodeMgr')
 
StopEvent = win32event.CreateEvent(None, 0, 0, None)
 
class CpEvent:
    def set_params(self, client, name, caller):
        self.client = client  # CP 실시간 통신 object
        self.name = name  # 서비스가 다른 이벤트를 구분하기 위한 이름
        self.caller = caller  # callback 을 위해 보관
 
    def OnReceived(self):
        # 실시간 처리 - 현재가 주문 체결
        if self.name == 'stockmst':
            print('recieved')
            win32event.SetEvent(StopEvent)
            return
 
 
class CpCurReply:
    def __init__(self, objEvent):
        self.name = "stockmst"
        self.obj = objEvent
 
    def Subscribe(self):
        handler = win32com.client.WithEvents(self.obj, CpEvent)
        handler.set_params(self.obj, self.name, None)
 
 
def MessagePump(timeout):
    waitables = [StopEvent]
    while 1:
        rc = win32event.MsgWaitForMultipleObjects(
            waitables,
            0,  # Wait for all = false, so it waits for anyone
            timeout, #(or win32event.INFINITE)
            win32event.QS_ALLEVENTS)  # Accepts all input
 
        if rc == win32event.WAIT_OBJECT_0:
            # Our first event listed, the StopEvent, was triggered, so we must exit
            print('stop event')
            break
 
        elif rc == win32event.WAIT_OBJECT_0 + len(waitables):
            # A windows message is waiting - take care of it. (Don't ask me
            # why a WAIT_OBJECT_MSG isn't defined < WAIT_OBJECT_0...!).
            # This message-serving MUST be done for COM, DDE, and other
            # Windowsy things to work properly!
            print('pump')
            if pythoncom.PumpWaitingMessages():
                break  # we received a wm_quit message
        elif rc == win32event.WAIT_TIMEOUT:
            print('timeout')
            return
            pass
        else:
            print('exception')
            raise RuntimeError("unexpected win32wait return value")
 
 
code = 'A005930'
 
##############################################################
#1. BlockRequest
print('#####################################')
objStockMst = win32com.client.Dispatch("DsCbo1.StockMst")
objStockMst.SetInputValue(0, code)
objStockMst.BlockRequest()
print('BlockRequest 로 수신 받은 데이터')
item = {}
item['종목명']= g_objCodeMgr.CodeToName(code)
item['현재가'] = objStockMst.GetHeaderValue(11)  # 종가
item['대비'] =  objStockMst.GetHeaderValue(12)  # 전일대비
print(item)
 
print('')
##############################################################
# 2. Request --> 메시지 펌프 -->  OnReceived 이벤트 수신
print('#####################################')
objReply = CpCurReply(objStockMst)
objReply.Subscribe()
 
code = 'A005930'
objStockMst.SetInputValue(0, code)
objStockMst.Request()
MessagePump(10000)
item = {}
item['종목명']= g_objCodeMgr.CodeToName(code)
item['현재가'] = objStockMst.GetHeaderValue(11)  # 종가
item['대비'] =  objStockMst.GetHeaderValue(12)  # 전일대비
print(item)



두 번째 방법에서는 이전에 올린 메시지 펌프를 이용해서 이벤트를 대기하도록 했습니다. 

2018/12/08 - [개발/파이썬] - 파이썬 윈도우 메시지 펌프 처리 예제

두 가지 방법은 장단점이 있습니다.

  • BlockRequest 방식 - 호출이 단순. 단, 실시간 시세 이벤트를 수신 받아 호출 할 경우 또 다시 시세 발생으로 재귀 호출 될 수 있음. 완전히 회피하기 위해서는 Request 방식을 사용해야 함. 
  • Request 호출 후 Received 이벤트를 수신 받기 - 호출과 수신 코드가 분리 되어 코딩이 BlockRequest 보다 어려움(위 코드는 메시지 펌프를 이용했으나 PYQT 같은 자체 메시지 펌프를 가진 윈도우에서는 Received 이벤트 처리 이후를 함수 호출로 처리하는 식으로 개발 해야 함.


목적에 따라 각자 필요한 함수를 이용하면 되겠습니다.