파이썬 초보 입니다. 도와주세용,...
안녕하세요. 선배님들.
파이썬 한달된 초보입니다.
증권사 api를 이용해서 데이터를 수신하는 작은 프로그램을 만들었는데 이게 자꾸 한 5분 실행되고나서 아래와 같은 메세지와 함께 실행이 종료되어 버립니다.
--------------------------------에러 메세지 ---------------
08-08 20:21:50 적재작업 실행중, 일반=1, 실시간=3, 주기=4
* end of Run() : 61초후 재실행 예약됨.
오토 파일럿 체킹
자율주행 체크해제 확인
Exception in thread Thread-228:
Traceback (most recent call last):
File "C:\Users\schan\anaconda3\envs\pythonProject5\lib\threading.py", line 932, in _bootstrap_inner
self.run()
File "C:\Users\schan\anaconda3\envs\pythonProject5\lib\threading.py", line 1254, in run
self.function(*self.args, self.kwargs)
File "C:/Users/schan/PycharmProjects/pythonProject5/adc_heroCondition_v0.0.3.py", line 807, in autoPilot
adc.execute(sql)
File "C:\Users\schan\anaconda3\envs\pythonProject5\lib\site-packages\pymysql\cursors.py", line 148, in execute
result = self._query(query)
File "C:\Users\schan\anaconda3\envs\pythonProject5\lib\site-packages\pymysql\cursors.py", line 310, in _query
conn.query(q)
File "C:\Users\schan\anaconda3\envs\pythonProject5\lib\site-packages\pymysql\connections.py", line 548, in query
self._affected_rows = self._read_query_result(unbuffered=unbuffered)
File "C:\Users\schan\anaconda3\envs\pythonProject5\lib\site-packages\pymysql\connections.py", line 775, in _read_query_result
Process finished with exit code -1073740791 (0xC0000409)
----------- 소스코드 ---------
-- coding: UTF-8 --
ui파일 py로 변환 : python -m PyQt5.uic.pyuic -x adc_heroCondition.ui -o untitled.py
exe 파일 컴파일: pyinstaller --onefile adc_heroCondition_v0.0.3.py adc_heroCondition.exe
import sys**
import time
from PyQt5.QtWidgets import *
from PyQt5 import uic
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QAxContainer import *
from PyQt5.QtWidgets import QMessageBox
import re
import pyautogui as pg
import threading
import pymysql
from PyQt5 import QtTest
import sqlite3
import os
from PyQt5.QtCore import QTime
import datetime as dt
UI파일 연결
단, UI파일은 Python 코드 파일과 같은 디렉토리에 위치해야한다.
form_class = uic.loadUiType("adc_heroCondition_v0.0.3.ui")[0]
프로그램 정보
progName = 'adc_영웅문 조건식 결과데이터 적재'
progVersion = '0.0.3'
progCode = '0156_condition'
progVsignCode = '0156_condition_VSIGN'
창닫기(X)버튼에 의한 프로그램 종료 루틴 진행중 여부
isProgExit = 0
api자동로그인 설정여부
isAutoApiLogin = 0
api로그인 걸린 시간 관련
stimeApi = 0
etimeApi = 0
현재 폴더위치
curDir = os.getcwd()
디폴트 작업시간
dTime = ('08:55:00', '15:30:00')
cTime = list()
조건식 번호/이름
condList = list()
api로그인상태
apiLoginState = False
api계정 ID
apiID = ''
현재 조건식의 타입
curCondType = ''
실시간 및 배치 조건식 수량
countBatch = 0
countReal = 0
dumy 조건식명
dumyCondName = "Rdont delete me"
foundDumyCond = False
db적재 실행 여부
doDatabaseUpdate = False
타이머 중지 여부
doStopTimer = True
현재 실행분 카운트
CountMin = 0
타이머 실행주기(초)
secTimer = 61
apSecTimer = 10
텍스트박스 클리어 여부
doClearTextbox = False
배치/실시간 이벤트 카운트
coutBEvent = 0
coutREvent = 0
작업 주기 현황
statusString = ''
오토파일럿에 의한 실행중단 여부
isByAutoPilot = 0
Run Count
runCount = 0
데이터베이스 연결
db = pymysql.connect(user='ddc_master', passwd='3314as', host='192.168.0.100', db='ddc', charset='utf8')
adc = db.cursor(pymysql.cursors.DictCursor)
오토커밋 끄기
sql = "set @@autocommit = 0;"
adc.execute(sql)
sqlite3 연결 및 초기화
if os.path.isfile(curDir + "\db.db"):
print(0)
sq3 = sqlite3.connect(curDir + "\db.db")
cur = sq3.cursor()
else:
print(1)
# sqlite3 초기화
sq3 = sqlite3.connect(curDir + "\db.db")
cur = sq3.cursor()
# 테이블 생성
sql = (
"create table job_schedule\n"
"(\n"
" start_time char(8),\n"
" end_time char(8)\n"
")\n"
";"
)
print(sql)
cur.execute(sql)
sql = (
"insert into job_schedule\n"
"values\n"
" ('" + dTime[0] + "', '" + dTime[1] + "')\n"
";"
)
print(sql)
cur.execute(sql)
sql = "commit;"
cur.execute(sql)
print('데이터베이스가 생성되었습니다.')
cur.execute("select start_time, end_time from job_schedule;")
row = cur.fetchone()
cTime = list(row)
print ('start_time = ' + cTime[0])
print ('end_time = ' + cTime[1])
class MyWindow(QMainWindow, form_class):
def init(self):
global progName, progVersion
super().init()
self.setupUi(self)
# 창 타이틀 변경
self.setWindowTitle(str(progName) + ' v' + str(progVersion))
# 작업시간 관련 컨트롤 초기화
tmpTime = cTime[0].split(':')
self.timeEdit.setTime(QTime(int(tmpTime[0]), int(tmpTime[1]), int(tmpTime[2]), 000))
tmpTime = cTime[1].split(':')
self.timeEdit_2.setTime(QTime(int(tmpTime[0]), int(tmpTime[1]), int(tmpTime[2]), 000))
#self.timeEdit.setTime(QTime(12, 12, 12, 12))
### 키움 OCX 컨트롤 바인딩
self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")
### 키움 이벤트 바인딩
# 조건검색, 비실시간
self.kiwoom.OnReceiveTrCondition.connect(self.Event_TrCondition)
# 조건검색, 실시간
self.kiwoom.OnReceiveRealCondition.connect(self.Event_RealCondition)
# 로그인 완료, CommConnect()
self.kiwoom.OnEventConnect.connect(self.Event_Connect)
# 조건식명 리스트 요청
self.kiwoom.OnReceiveConditionVer.connect(self.Event_ConditionVer)
# 윈도우 컨트롤 액션 바인딩
self.pushButton.clicked.connect(self.button1Function)
self.pushButton_2.clicked.connect(self.button2Function)
self.pushButton_3.clicked.connect(self.button3Function)
self.pushButton_4.clicked.connect(self.button4Function)
self.pushButton_7.clicked.connect(self.button7Function)
def closeEvent(self, event):
global isProgExit
self.deleteLater()
ret = pg.confirm(text='프로그램을 종료하시겠습니까?', title='프로그램 종료 확인', buttons=['OK', 'Cancel'])
if ret == 'Cancel':
event.ignore()
else:
isProgExit = 1
self.button3Function()
event.accept()
print('##### 프로그램 종료 #####')
QCoreApplication.instance().quit()
# Api 이벤트 함수
def Event_Connect(self, err_code):
global apiLoginState, apiID, isAutoApiLogin, stimeApi, etimeApi
if err_code == 0:
self.show()
print('로그인 완료')
TR = 'GetLoginInfo("USER_ID")'
apiID = self.kiwoom.dynamicCall(TR)
self.statusBar().showMessage('키움증권 OpenApi 로그인 완료, ' + apiID)
apiLoginState = True
etimeApi = int(dt.datetime.now().strftime('%H:%M:%S').replace(':', ''))
# 로그인 하는데 걸린 시간을 측정하여, 사용자에게 자동 로그인을 하도록 유도
isAutoApiLogin = 1
""" 가상윈도우에서는 실행속도가 느려서 항상 이 메세지가 나오른 바람에 막아 놓음.
if etimeApi - stimeApi > 15:
ret = pg.confirm(text='혹시 키움증권 OpenApi에 수동으로 로그인 하셨나요?\napi 자동 로그인이 설정되어 있지 않으면 프로그램이 정상적으로 동작하지 않습니다.', title='키움증권 OpenApi 자동 로그인 설정', buttons=['이미 자동로그인이 설정되어 있음', '지금 자동로그인 설정하기'])
if ret == '이미 자동로그인이 설정되어 있음':
isAutoApiLogin = 1
elif ret == '지금 자동로그인 설정하기':
self.button7Function()
else:
isAutoApiLogin = 1
"""
else:
print('로그인 실패')
self.statusBar().showMessage('키움증권 OpenApi 로그인 실패!!!, ' + ret)
apiLoginState = False
#자율주행모드 시작
autoPilot()
def Event_ConditionVer(self, lRet, sMsg):
global condList, apiID
if lRet == 1:
# self.textEdit.clear()
self.textEdit.append('작업대상 조건식 목록 >')
TR = "GetConditionNameList ()"
ret = self.kiwoom.dynamicCall(TR)
Lines = tuple(ret.split(';'))
condList.clear()
if len(condList) == 0:
for i in Lines:
temp = i.split('^')
if len(temp) == 2 and (temp[1][0:2] == 'R_' or temp[1][0:2] == 'B_'):
condList.append((temp[0], temp[1]))
for i in condList:
self.textEdit.append(' ' + i[0] + ' :: ' + i[1])
### 데이터 적재
if i[1] != dumyCondName:
# 중복 제거
sql = (
"delete from Hero_ConditionScan_Index\n"
"where\n"
" hts_id = '" + str(apiID) + "'\n"
" and cond_nm = '" + str(i[1]) + "'\n"
";"
)
# print(sql)
adc.execute(sql)
# 적재
sql = (
"insert into Hero_ConditionScan_Index\n"
"set\n"
" date = '" + getCurTime('YDATE') + "',\n"
" hts_id = '" + str(apiID) + "',\n"
" cond_cd = '" + str(i[0]) + "',\n"
" cond_nm = '" + str(i[1]) + "',\n"
" create_dttm = curtime()"
";"
)
# print(sql)
adc.execute(sql)
# 커밋
sql = "commit;"
adc.execute(sql)
else:
pg.alert(text='condList 초기화에 실패 하였습니다.', title='초기화 실패', button='OK')
# 1회성 결과
def Event_TrCondition(self, sScrNo, strCodeList, strConditionName, nIndex, nNext):
global adc, doDatabaseUpdate, apiID, dumyCondName, coutBEvent
# mysql 커서 초기화, 409 에러가 해결될까?
adc.close()
adc = db.cursor(pymysql.cursors.DictCursor)
if doDatabaseUpdate:
# 더미 조건식의 데이터는 수집하지 않음
if strConditionName == dumyCondName:
return
#텍스트 박스에 출력
coutBEvent = coutBEvent + 1
if coutBEvent == 1:
self.textEdit_2.clear()
self.textEdit_2.append('\n' + strConditionName + ' > ' + strCodeList)
#### 데이터 적재
# 기존 레코드 삭제
sql = (
"delete from Hero_ConditionScan_Items\n"
"where\n"
" date = '" + getCurTime('YDATE') + "'\n"
" and HTS_ID = '" + apiID + "'\n"
" and COND_NM = '" + strConditionName + "'\n"
";"
)
# print(sql)
adc.execute(sql)
# 적재
codeList = strCodeList.split(';')
for code in codeList:
# print(str(code))
code = code.strip()
if len(code) < 1:
continue
sql = (
"insert into Hero_ConditionScan_Items\n"
"set\n"
" date = '" + getCurTime('YDATE') + "',\n"
" HTS_ID = '" + str(apiID) + "',\n"
" COND_CD = '" + str(nIndex) + "',\n"
" COND_NM = '" + str(strConditionName) + "',\n"
" item_cd = '" + str(code) + "',\n"
" create_dttm = curtime()\n"
";"
)
# print(sql)
adc.execute(sql)
# 커밋
sql = "commit;"
# print(sql)
adc.execute(sql)
else:
print('Event_TrCondition 실행할 수 없음.')
return
# 실시간 결과
def Event_RealCondition(self, strCode, strType, strConditionName, strConditionIndex):
global doDatabaseUpdate, coutREvent
if not doDatabaseUpdate:
return
coutREvent = coutREvent + 1
if coutREvent == 1:
self.textEdit_3.clear()
self.textEdit_3.append(strConditionName + ' > ' + strType + ':' + strCode)
### 데이터 적재
# 기존 레코드 삭제
sql = (
"delete from Hero_ConditionScan_Items\n"
"where\n"
" date = '" + getCurTime('YDATE') + "'\n"
" and HTS_ID = '" + str(apiID) + "'\n"
" and COND_NM = '" + str(strConditionName) + "'\n"
" and ITEM_CD = '" + str(strCode) + "'\n"
";"
)
# print(sql)
adc.execute(sql)
# 종목 편입
if strType.upper() == 'I':
sql = (
"insert into Hero_ConditionScan_Items\n"
"set\n"
" date = '" + getCurTime('YDATE') + "',\n"
" HTS_ID = '" + str(apiID) + "',\n"
" COND_CD = '" + str(strConditionIndex) + "',\n"
" COND_NM = '" + str(strConditionName) + "',\n"
" item_cd = '" + str(strCode) + "',\n"
" create_dttm = curtime()\n"
";"
)
#print(sql)
adc.execute(sql)
# 종목 이탈
elif strType.upper() == 'D':
# 위에서 이미 해당 종목을 delete 했기 때문에 여기서는 아무것도 안함.
pass
else:
pg.alert(text='인식할 수 없는 strType 값 입니다.(' + strType + ')', title='인식불가 strType', button='OK')
self.button3Function()
return
# 커밋
sql = "commit;"
# print(sql)
adc.execute(sql)
#####################
##### 사용자 함수 #####
#####################
##### 사용자 함수
def isApiLogin(self):
global apiLoginState
ret = self.kiwoom.dynamicCall("GetConnectState()")
apiLoginState = ret
return ret
def apiLogin(self):
global stimeApi
# 키움 로그인
stimeApi = int(dt.datetime.now().strftime('%H:%M:%S').replace(':', ''))
self.kiwoom.dynamicCall("CommConnect()")
print('로그인 시작')
def getConnectState(self):
# 키움 로그인 상태
TR = 'GetConnectState()'
ret = self.kiwoom.dynamicCall(TR)
print('ret=' + ret)
return ret
##### 컨트롤 Action 함수
#현재 조건식 목록 보기 버튼
def button1Function(self):
global isAutoApiLogin
# 키움 조건식명 리스트 가져오기
if isAutoApiLogin == 1:
TR = 'GetConditionLoad()'
self.kiwoom.dynamicCall(TR)
else:
pg.alert(text='키움증권 OpenApi 자동로그인 설정을 먼저 수행하세요.', title='키움증권 OpenApi 자동로그인 설정 안내', button='OK')
#시작 버튼
def button2Function(self):
global doStopTimer, doDatabaseUpdate, isByAutoPilot
if doStopTimer and isAutoApiLogin == 1:
if isByAutoPilot == 0:
self.textEdit.clear()
# 상태 레이블
self.textEdit.append(getCurTime('DATE') + ' ' + getCurTime('TIME') + ' 작업 준비중,...')
self.lineEdit.setText(getCurTime('DATE') + ' ' + getCurTime('TIME') + ' 작업 준비중,...')
doStopTimer = False
doDatabaseUpdate = True
self.RUN()
print("doDatabaseUpdate : ", doDatabaseUpdate)
elif not doStopTimer:
pg.alert(text='이미 데이터 적재작업이 진행중 입니다.', title='작업 진행중', button='OK')
elif isAutoApiLogin == 0:
pg.alert(text='키움증권 OpenApi 자동로그인 설정이 되어 있지 않습니다.', title='키움증권 OpenApi 자동로그인 설정 안내', button='OK')
isByAutoPilot = 0
def RUN(self):
global condList, curCondType, countBatch, countReal, dumyCondName, foundDumyCond, doStopTimer, CountMin, secTimer, coutBEvent, coutREvent, statusString, isByAutoPilot, apiLoginState, apTimer
timer = threading.Timer(secTimer, self.RUN)
if not doStopTimer:
# doStopTimer = True
CountMin = CountMin + 1
print('* start of Run() : 주기' + str(CountMin))
# 로그인 확인후 로그아웃 상태이면 로그인 처리
if not self.isApiLogin:
self.textEdit.append('키움증권 OpenApi 로그아웃 상태 확인됨. 로그인 시도.')
print('키움증권 OpenApi 로그아웃 상태 확인됨. 로그인 시도.')
self.apiLogin()
if not apiLoginState:
self.textEdit.append('키움증권 OpenApi 로그인 실패!!! 작업 중지.')
print('키움증권 OpenApi 로그인 실패!!! 작업 중지.')
# 모든 타이머 종료후 작업 중지
timer.cancel()
apTimer.cancel()
self.button3Function()
return
else:
self.textEdit.append('키움증권 OpenApi 로그완료.')
print('키움증권 OpenApi 로그인 완료.')
# GetConditionLoad에 대한 응답 이벤트로 조건명리스트가 왔으면,..
condList = list()
for i in range(0,100):
print('조건식명 리스트 조회 ' + str(i) + '회전')
if len(condList) < 1:
# 키움 조건식명 리스트 가져오기
TR = 'GetConditionLoad()'
self.kiwoom.dynamicCall(TR)
# time.sleep(0.2)
QtTest.QTest.qWait(1000)
else:
break
if len(condList) < 1:
### 알수 없는 이유로 조건식명 리스트 조회가 실패함.
msg = "조건식명 리스트가 조회되지 않았습니다."
print(msg)
self.textEdit_2.append(msg)
# 자율주행 끄기
isByAutoPilot = 1
self.groupBox.setChecked(False)
# 작업 중지
self.button3Function()
return
#### 키움 조건식 결과종목 가져오기
# 조건식명 오류 처리
for i in range(0, len(condList)):
# 조건식명은 R_ or B_로 시작해야 하며, 한글이 포함되어서는 안된다.(한글 포함시 SendCondition TR 보낼때 에러남.)
if (condList[i][1][0:2] != 'R_' and condList[i][1][0:2] != 'B_') or isHangul(condList[i][1]):
pg.alert(text='인식할 수 없는 조건식명 이거나 한글이 포함된 조건식명 입니다.(' + condList[i][1] + ')', title='조건식명 오류', button='OK')
self.button3Function()
return
"""
# 실시간 조회 중지 TR, 직전의 오류로 인해서 실시간 조건식이 아닌데도 실시간 TR로 등록된 경우를 대비하여 모든 조건식에 대해서 실시간 중지 날림.
for i in range(0, len(condList)):
condType = condList[i][1][0:1]
if condType == 'R':
TR = 'SendConditionStop("0156", "' + condList[i][1] + '", "' + condList[i][0] + '")'
ret = self.kiwoom.dynamicCall(TR)
print('실시간 검색 해지 : ', end="")
print(TR)
print('ret=', ret)
# time.sleep(0.2)
QtTest.QTest.qWait(300)
"""
"""
TR = 'SetRealRemove("ALL", "ALL")'
ret = self.kiwoom.dynamicCall(TR)
QtTest.QTest.qWait(1000)
"""
# 일반 조회 TR
print('--- 일반 조회 TR')
countBatch = 0
coutBEvent = 0
failCount = 0
for i in range(0, len(condList)):
# TR 구성
if condList[i][1][0:2] == 'B_':
print(condList[i][1])
curCondType = 'B'
countBatch = countBatch + 1
TR = 'SendCondition("0156", "' + condList[i][1] + '", ' + condList[i][0] + ', 0)'
print(TR)
for j in range(0, 61):
ret = self.kiwoom.dynamicCall(TR)
print('ret=' + str(ret))
# 요청한 조건식이 없거나 조건 고유번호와 조건명이 서로 안맞거나 조회횟수를 초과하는 경우 실패하게 됨.
if ret == 0:
#타이머 취소
if j == 0:
print('타이머를 취소 합니다.')
timer.cancel()
failCount = failCount + 1
# print("failCount=" + str(failCount))
self.textEdit.append("일반, " + str(condList[i][1]) + ", failCount=" + str(failCount))
# time.sleep(1)
QtTest.QTest.qWait(1000)
else:
break
print('조회요청 조건식:' + str(condList[i][1]))
print(ret)
if ret == 0:
pg.alert(text = str(i) + ' :: <' + condList[i][1] + '> 조건식결과 일반조회 등록에 실패하였습니다.', title = '조건식결과 조회 등록 실패', button = 'OK')
self.button3Function()
return
QtTest.QTest.qWait(300)
# 실시간 조회 TR
if CountMin == 1:
print('--- 실시간 조회 TR')
countReal = 0
coutREvent = 0
failCount = 0
for i in range(0, len(condList)):
# TR 구성
if condList[i][1][0:2] == 'R_':
curCondType = 'R'
countReal = countReal + 1
# 첫번째 실시간 조건식이면 1초간 시간지연, Rdon't delete me 조건식이 확실하게 가장 먼저 OnReceiveTrCondition 이벤트에 데이터가 들어오게 하기 위함.
# 첫번째로 OnReceiveTrCondition에 데이터를 수신한 조건식은 실시간 TR에서 데이터가 안들어오는 api 버그가 관찰됨.
# 따라서, Rdon't delete me 조건식을 항상 가장먼저 수신하게 해서 오류를 우회함.
if condList[i][1] == dumyCondName:
foundDumyCond = True
print('조건식:', condList[i][1])
TR = 'SendCondition("0156", "' + condList[i][1] + '", ' + condList[i][0] + ', 1)'
print(TR)
for j in range(0, 61):
ret = self.kiwoom.dynamicCall(TR)
print('ret=' + str(ret))
# 요청한 조건식이 없거나 조건 고유번호와 조건명이 서로 안맞거나 조회횟수를 초과하는 경우 실패하게 됨.
if ret == 0:
#타이머 취소
if j == 0:
print('타이머를 취소 합니다.')
timer.cancel()
failCount = failCount + 1
print("failCount=", failCount)
self.textEdit.append("실시간, " + str(condList[i][1]) + ", failCount=" + str(failCount))
# time.sleep(1)
QtTest.QTest.qWait(1000)
else:
break
if ret == 0:
pg.alert(text=str(i) + ' :: <' + condList[i][1] + '> 조건식결과 실시간조회 등록에 실패하였습니다.', title='조건식결과 조회 등록 실패', button='OK')
self.button3Function()
return
QtTest.QTest.qWait(1000)
if not foundDumyCond:
pg.alert(text='더미 조건식명이 발견되지 않았습니다..', title='더미 조건식 없음', button='OK')
self.button3Function()
return
# 상태 레이블
statusString = getCurTime('DATE') + ' ' + getCurTime('TIME') + ' 적재작업 실행중, 일반=' + str(countBatch) + ', 실시간=' + str(countReal) + ', 주기=' + str(CountMin)
print(statusString)
self.textEdit.append(statusString)
self.lineEdit.setText(statusString)
# 1분후 함수 재실행
#threading.Timer(secTimer, self.RUN).start()
timer.start()
print('* end of Run() : ' + str(secTimer) + '초후 재실행 예약됨.')
# doStopTimer = False
else:
return
### 중지 버튼
def button3Function(self):
global condList, doDatabaseUpdate, doStopTimer, isByAutoPilot, isProgExit, countMin
if doStopTimer:
if isByAutoPilot == 0:
if isProgExit == 0:
countMin = 0
pg.alert(text='실행중이 아닙니다.', title='실행 중지', button='OK')
return
else:
if isByAutoPilot == 0:
if isProgExit == 0:
ret = pg.confirm(text='데이터 적재 작업을 중지하시겠습니까?', title='작업 중지', buttons=['OK', 'Cancel'])
if ret == 'Cancel':
return
# 상태 레이블
self.textEdit.append(getCurTime('DATE') + ' ' + getCurTime('TIME') + ' 중지됨')
self.lineEdit.setText(getCurTime('DATE') + ' ' + getCurTime('TIME') + ' 중지됨')
# DB 업데이트 중지
doStopTimer = True
doDatabaseUpdate = False
# 실시간 이벤트 해지
for i in range(0, len(condList)):
TR = 'SendConditionStop("0156", "' + condList[i][1] + '", "' + condList[i][0] + '")'
self.kiwoom.dynamicCall(TR)
# time.sleep(0.2)
QtTest.QTest.qWait(300)
"""
TR = 'SetRealRemove("ALL", "ALL")'
ret = self.kiwoom.dynamicCall(TR)
QtTest.QTest.qWait(1000)
"""
countMin = 0
isByAutoPilot = 0
#종료 버튼
def button4Function(self):
global cTime
stime = self.timeEdit.time()
etime = self.timeEdit_2.time()
print(stime.toString())
print(etime.toString())
# 현재 설정된 작업시간과 동일하면 변경작업 안함
if cTime[0] == str(stime.toString()) and cTime[1] == str(etime.toString()):
return
# 사용자 메시지
ret = pg.confirm(text='작업 시간을 변경 하시겠습니까?\n\n *시작 : ' + stime.toString() + '\n *종료 : ' + etime.toString(), title='작업시간 변경', buttons=['OK', 'Cancel'])
if ret == 'Cancel':
return
#sqlite에 저장
sql = (
"update job_schedule\n"
"set\n"
" start_time = '" + stime.toString() + "',\n"
" end_time = '" + etime.toString() + "'\n"
";"
)
print(sql)
cur.execute(sql)
sql = "commit;"
cur.execute(sql)
cTime[0] = str(stime.toString())
cTime[1] = str(etime.toString())
print('start_time = ' + cTime[0])
print('end_time = ' + cTime[1])
'''
cur.execute("select * from job_schedule;")
row = cur.fetchall()
print(row)
'''
def button7Function(self):
global isAutoApiLogin
# 키움 조건식 결과종목 가져오기
TR = 'KOA_Functions("ShowAccountWindow", "")'
print(TR)
ret = self.kiwoom.dynamicCall(TR)
ret = pg.confirm(text='자동 로그인 설정을 완료하셨나요?', title='자동로그인 설정여부 확인', buttons=['예', '아니오'])
if ret == '예':
isAutoApiLogin = 1
elif ret == '아니오':
isAutoApiLogin = 0
pg.alert(text='자동 로그인 설정을 하지 않으면 프로그램이 정상적으로 동작하지 않습니다.\n반드시 자동 로그인 설정을 하시기 바랍니다.', title='자동로그인 설정 안내', button='OK')
def sleep(self, n):
# 1/1000 초 단위 임. 1초 = 1000
QtTest.QTest.qWait(n)
전역 함수
한글 포함여부 확인 함수
def isHangul(text):
#Check the Python Version
pyVer3 = sys.version_info >= (3, 0)
if pyVer3 : # for Ver 3 or later
encText = text
else: # for Ver 2.x
if type(text) is not unicode:
encText = text.decode('utf-8')
else:
encText = text
hanCount = len(re.findall(u'[\u3130-\u318F\uAC00-\uD7A3]+', encText))
return hanCount > 0
def getCurTime(parmDiv):
tm = time.localtime(time.time())
if parmDiv.upper() == 'YDATE':
# 날짜 YYYY-MM-Dd
return str(time.strftime('%Y-%m-%d', tm))
if parmDiv.upper() == 'DATE':
# 날짜 MM-DD
return str(time.strftime('%m-%d', tm))
if parmDiv.upper() == 'MONTH':
# 년
return str(time.strftime('%Y', tm))
if parmDiv.upper() == 'MONTH':
# 월
return str(time.strftime('%m', tm))
if parmDiv.upper() == 'DAY':
# 일
return str(time.strftime('%d', tm))
if parmDiv.upper() == 'TIME':
# 시간 시:분:초 24시간제
return str(time.strftime('%H:%M:%S', tm))
def autoPilot():
global myWindow, cTime, doStopTimer, apTimer, isByAutoPilot, isAutoApiLogin, progVsignCode, apiID
# 자율주행 켜짐 확인
print('오토 파일럿 체킹')
if myWindow.groupBox.isChecked() == True:
if doStopTimer:
myWindow.textEdit.append(getCurTime('TIME') + " >> auto pilot : 자율주행 활성 상태")
# 작업시간 확인 후 시작/중지 실행
curTime = int(dt.datetime.now().strftime('%H:%M:%S').replace(':', ''))
print('curTime = ' + str(curTime) + ', cTime[0] = ' + cTime[0].replace(':', '') + ', cTime[1] = ' + cTime[1].replace(':',''))
if curTime >= int(cTime[0].replace(':', '')) and curTime < int(cTime[1].replace(':','')):
if doStopTimer:
myWindow.textEdit.append(">> auto pilot : 작업시간 대기 상태")
print('작업시간 확인')
#작업시간 이면, 현재 작업상태 확인후 시작안했으면 시작 시키기
isByAutoPilot = 0
if doStopTimer == True and isAutoApiLogin == 1:
#작업 시작
myWindow.textEdit.append(getCurTime('TIME') + " >> auto pilot : 작업시간 확인, 작업 시작!!!")
isByAutoPilot = 1
myWindow.textEdit.append(">> auto pilot : 작업 시작!!!")
print('오토파일럿에 의한 자동 시작')
myWindow.button2Function()
else:
if doStopTimer:
myWindow.textEdit.append(getCurTime('TIME') + " >> auto pilot : 작업시간 대기")
myWindow.textEdit.moveCursor(QtGui.QTextCursor.End)
print('작업시간 아님 확인')
# 작업시간이 아니면, 현재 작업상태 확인후 시작했으면 종료 시키기
isByAutoPilot = 0
if doStopTimer == False:
#작업 중지
isByAutoPilot = 1
myWindow.textEdit.append(">> auto pilot : 작업 중지!!!")
print('오토파일럿에 의한 자동 종료')
myWindow.button3Function()
else:
if doStopTimer:
myWindow.textEdit.append(getCurTime('TIME') + " >> auto pilot : 자율주행 비활성 상태")
myWindow.textEdit.moveCursor(QtGui.QTextCursor.End)
print('자율주행 체크해제 확인')
#바이탈 사인
sql = "select count(*) from program_vsign where program_cd = '" + progVsignCode + "' and user_id = '" + apiID + "';"
adc.execute(sql)
row = adc.fetchone()
print("바이탈 사인 기록 절차 시작")
if row['count(*)'] == 0:
# insert
print("insert 시작")
sql = (
"insert into program_vsign\n"
"set\n"
" program_cd = '" + progVsignCode + "',\n"
" user_id = '" + apiID + "',\n"
" comment = '영웅문 조건식 결과종목 적재',\n"
" time_stamp = curtime(),\n"
" create_dttm = curtime()\n"
";"
)
print("바이탈 사인 Insert 쿼리 설정 완료.")
else:
# update
print("update 시작")
sql = (
"update program_vsign\n"
"set\n"
" time_stamp = curtime()\n"
"where\n"
" program_cd = '" + progVsignCode + "'\n"
" and user_id = '" + apiID + "'\n"
";"
)
print("바이탈 사인 Update 쿼리 설정 완료.")
print(sql)
adc.execute(sql)
sql = "commit;"
print(sql)
adc.execute(sql)
# 자율주행 타이머 재호출 등록
apTimer = threading.Timer(apSecTimer, autoPilot)
apTimer.start()
return
def displayCurTime():
myWindow.lcdNumber.display(getCurTime('TIME'))
cTimer = threading.Timer(1, displayCurTime)
cTimer.start()
return
if name == "main":
app = QApplication(sys.argv)
myWindow = MyWindow()
myWindow.apiLogin()
#myWindow.show()
myWindow.lcdNumber.setDigitCount(8)
displayCurTime()
app.exec_()
조그마한 힌트라도 부탁드리겠습니다.
제 느낌에는 타이머 쓰레드가 문제가 아닌가 싶습니다만,...
이리저리 검색해봐도 감을 잡을수가 없네요.
(쓰레드는 정말 어렵네요,... )
감사합니다.
김한솔 님 1669
M 2021년 8월 8일 9:16 오후