You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt5程序随机触发exit code -1073740791错误排查求助

问题背景

基于PyQt5 + Python3.9开发的批量数据下载程序,通过QEventLoop.exec_()向服务器发起请求,接收完所有数据后调用QEventLoop.exit()结束循环。程序处理约1000个任务时,会随机触发错误码-1073740791(0xC0000409)崩溃,崩溃点无固定规律,可能出现在任务前、中、后期,甚至不出现。经初步排查,怀疑频繁开关文件是诱因。

请求数据代码片段:

def day_kiwoom_db(self, code=None, date=None, sPrevNext="0"):
    QTest.qWait(3600)

    self.temp_screen1 += 1
    if self.temp_screen1 >= 150:
        self.temp_screen1 = 0
        self.temp_screen3 += 1

    self.dynamicCall("SetInputValue(QString, QString)", "종목코드", code)
    self.dynamicCall("SetInputValue(QString, QString)", "수정주가구분", "1")

    if date != None:
        self.dynamicCall("SetInputValue(QString, QString)", "기준일자", date)

    self.dynamicCall("CommRqData(QString, QString, int, QString)", "주식일봉차트조회", "opt10081", sPrevNext, "%s" % (int(self.screen_calculation_stock) + self.temp_screen3))

    self.calculator_event_loop.exec_()

接收数据代码片段(存在缩进错误):

def trdata_slot(self, sScrNo, sRQName, sTrCode, sRecordName, sPrevNext):

    if sRQName == "주식일봉차트조회":
        code = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "종목코드")
        code = code.strip()


        cnt = self.dynamicCall("GetRepeatCnt(QString, QString)", sTrCode, sRQName)


        for i in range(cnt):
            close_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "현재가") 
            close_price = close_price.strip().lstrip('+').lstrip('-')

            value = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "거래량")  
        value = value.strip()

            trading_value = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "거래대금")  # 출력 : 000070
        trading_value = trading_value.strip()

            date = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "일자")  
            date = date.strip()

            start_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "시가")  # 출력 : 000070
            start_price = start_price.strip().lstrip('+').lstrip('-')

            high_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "고가")  # 출력 : 000070
            high_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "고가")
            high_price = high_price.strip().lstrip('+').lstrip('-')

            low_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "저가")  # 출력 : 000070
            low_price = low_price.strip().lstrip('+').lstrip('-')

            print("%s,%s,%s,%s,%s,%s\n" % (date, start_price, close_price, high_price, low_price, value))

            f = open(self.datafile_path, "a", encoding="utf8")
            f.write("%s,%s,%s,%s,%s,%s\n" % (date, start_price, close_price, high_price, low_price, value))
            f.close()


        if sPrevNext == "2" and self.chart_req_time > 0:
            self.day_kiwoom_db(code=code, sPrevNext=sPrevNext)
            self.chart_req_time -= 1
        else:
            print("총 일수 %s" % len(self.calcul_data))
            self.chart_req_time = self.chart_req_tmp
            self.calculator_event_loop.exit()
解决思路与修复方案

1. 修复代码缩进错误

原接收数据代码中,value = value.strip()和trading_value = trading_value.strip()的缩进跳出了for循环,会导致变量值异常,触发不可预期的错误。必须将这两行代码缩进至for循环内部。

2. 优化文件IO操作

频繁的open()/close()会增加系统资源开销,容易引发资源竞争或句柄泄漏。优化方案:

  • 内存缓存批量数据,一次性写入文件
  • 单个任务周期内保持文件打开状态

修改后的接收数据代码(批量写入版):

def trdata_slot(self, sScrNo, sRQName, sTrCode, sRecordName, sPrevNext):
    if sRQName == "주식일봉차트조회":
        code = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "종목코드")
        code = code.strip()

        cnt = self.dynamicCall("GetRepeatCnt(QString, QString)", sTrCode, sRQName)
        # 内存缓存数据,减少IO次数
        data_lines = []
        for i in range(cnt):
            close_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "현재가") 
            close_price = close_price.strip().lstrip('+').lstrip('-')

            value = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "거래량")  
            value = value.strip()  # 修复缩进

            trading_value = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "거래대금")
            trading_value = trading_value.strip()  # 修复缩进

            date = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "일자")  
            date = date.strip()

            start_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "시가")
            start_price = start_price.strip().lstrip('+').lstrip('-')

            high_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "고가")
            high_price = high_price.strip().lstrip('+').lstrip('-')

            low_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "저가")
            low_price = low_price.strip().lstrip('+').lstrip('-')

            line = "%s,%s,%s,%s,%s,%s\n" % (date, start_price, close_price, high_price, low_price, value)
            print(line.strip())
            data_lines.append(line)
        
        # 批量写入文件,添加异常捕获
        if data_lines:
            try:
                with open(self.datafile_path, "a", encoding="utf8") as f:
                    f.writelines(data_lines)
            except IOError as e:
                print(f"文件写入失败: {e}")
                # 可选:将失败数据缓存,后续重试

        if sPrevNext == "2" and self.chart_req_time > 0:
            self.day_kiwoom_db(code=code, sPrevNext=sPrevNext)
            self.chart_req_time -= 1
        else:
            print("총 일수 %s" % len(self.calcul_data))
            self.chart_req_time = self.chart_req_tmp
            self.calculator_event_loop.exit()

3. 错误码0xC0000409的额外排查点

该错误对应Windows的STATUS_STACK_BUFFER_OVERRUN,除文件IO外,还需排查:

  • 字符串处理时的缓冲区溢出(如strip()或字符串拼接异常)
  • dynamicCall调用时参数类型不匹配,导致内存访问错误
  • Kiwoom接口的线程安全问题,避免并发请求过载

4. 事件循环与并发优化

  • PyQt槽函数运行在主线程,大量IO操作可能阻塞事件循环,可将文件写入移至QThreadPool单独处理
  • 调整QTest.qWait(3600)的等待时间为更合理值,或用信号量控制并发请求数量,避免接口过载

内容的提问来源于stack exchange,提问作者gety

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 06:35:19