代码在调试模式下运行但不是正常[重复]

Posted

技术标签:

【中文标题】代码在调试模式下运行但不是正常[重复]【英文标题】:Code runs in debug mode but not in normal [duplicate] 【发布时间】:2021-07-02 06:23:19 【问题描述】:

我正在开发软件,其中包括使用 WHO ICD11 API 的部分。 当我运行代码时:

import json
import re
import threading
import time
from typing import Dict, List

import qdarkgraystyle as qdarkgraystyle
import requests
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import pyqtSignal, QThread
from PyQt5.QtWidgets import QTreeView
from threading import Lock
from gui import Ui_MainWindow
import auth

printlock = Lock()
p = print


def print(*a, **b):
    with printlock:
        p(*a, **b)


class g:
    max = 1
    progress = 0
    end_workers = False
    loaded_dict = None


class ApplicationWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(ApplicationWindow, self).__init__()
        
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)


def linearization_url():
    return f"https://id.who.int/icd/release/ui.dropRevision.currentText().split('/')[0]/ui.dropRelease.currentText()('/' + ui.dropRevision.currentText().split('/')[1]) if len(ui.dropRevision.currentText().split('/')) > 1 else ''"


def download():
    loader = Loader(linearization_url())
    loader.statusUpdateHook.connect(updatehook)
    loader.statusFinished.connect(finishedLoader)
    loader.start()


def updatehook():
    ui.progress.setTextVisible(True)
    ui.progress.setMaximum(gl.max)
    ui.progress.setValue(gl.progress)


def finishedLoader():
    json.dump(gl.loaded_dict, open("dict.json"), indent=4)


def split_link(url: str) -> Dict[str, str]:
    return re.search(
            "https?://id.who.int/icd/release/(?P<revision>[0-9]2)/(?P<release>[^/]*)(/(?P<linearization>.*))?",
            url).groupdict()


def worker(loader):
    print("Worker booting...")
    _token = gl.token
    over = True
    while not gl.end_workers:
        url = ""
        with loader.index_lock:
            try:
                url = loader.working_list[loader.index]
                loader.index += 1
            except IndexError:
                over = False
        if over:
            json = request_json(url, _token)
            with loader.finished_count_lock:
                loader.working_dict[url] = json
                if "child" in json:
                    for child in json["child"]:
                        loader.working_list.append(child)
                loader.finished_count += 1
        else:
            over = True


def loadReleases():
    token = getToken(auth.id, auth.secret)
    ui.dropRelease.clear()
    ui.dropRelease.repaint()
    for release in request_json("https://id.who.int/icd/release/" + ui.dropRevision.currentText(), token)[
        "release"]:
        ui.dropRelease.addItem(split_link(release)["release"])


def getToken(clientID, clientSecret) -> str:
    return requests.post('https://icdaccessmanagement.who.int/connect/token',
                         data='client_id':  clientID, 'client_secret': clientSecret, 'scope': 'icdapi_access',
                               'grant_type': 'client_credentials').json()['access_token']


def request_json(link_: str, token_: str):
    headers_ = 
        'Authorization':   'Bearer ' + token_,
        'Accept':          'application/json',
        'Accept-Language': 'en',
        'API-Version':     'v2'
    
    return requests.get(link_, headers=headers_).json()


class Loader(QtCore.QThread):
    statusFinished = QtCore.pyqtSignal()
    statusUpdateHook = QtCore.pyqtSignal()
    index = 0
    finished_count = 0
    working_list = []
    working_dict = 
    index_lock = Lock()
    finished_count_lock = Lock()
    workers = []
    
    def __init__(self, lurl: str):
        super().__init__()
        self.working_list.append(lurl)
    
    def progressUpdate(self):
        gl.max = len(self.working_list)
        gl.progress = self.finished_count
        self.statusUpdateHook.emit()
    
    def run(self):
        for i in range(0, 20):
            self.workers.append(threading.Thread(target=worker, args=(self,)))
            self.workers[i].start()
        while self.finished_count < len(self.working_list):
            with self.index_lock:
                with self.finished_count_lock:
                    self.progressUpdate()
            time.sleep(5)
        for work in self.workers:
            if work.isAlive():
                gl.end_workers = True
        gl.loaded_dict = self.working_dict
        self.statusFinished.emit()


if __name__ == "__main__":
    import sys
    
    gl = g()
    gl.token = getToken(auth.id, auth.secret)
    tabs: List[QTreeView] = []
    app = QtWidgets.QApplication(sys.argv)
    application = ApplicationWindow()
    application.setStyleSheet(qdarkgraystyle.load_stylesheet())
    ui = application.ui
    ui.buttonDownload.clicked.connect(download)
    ui.dropRevision.addItems(["10", "11/mms"])
    ui.dropRevision.currentIndexChanged.connect(loadReleases)
    loadReleases()
    application.show()
    sys.exit(app.exec_())

在 Pycharms 调试模式下,它确实是我想要的。只要在调试模式下它就可以正常工作,而在正常模式下,当触发buttonDownload.clicked事件时,整个程序崩溃,唯一的输出是:

QThread: Destroyed while thread is still running

有人知道如何解决这个问题吗?

(出于复制目的:您需要 API 密钥才能访问 API。它们从 auth 导入为 auth.id 和 auth.secret。ID 和密钥可以从the WHO ICD11 API site 上的帐户获得)

【问题讨论】:

【参考方案1】:

Loader 继承QThread,在download 函数QThread 对象绑定到局部变量loader,在退出函数时,此变量被垃圾收集并且绑定对象被销毁。您需要确保loader 变量超出函数的寿命,例如使其成为全局变量或从函数返回并存储在某处。

【讨论】:

以上是关于代码在调试模式下运行但不是正常[重复]的主要内容,如果未能解决你的问题,请参考以下文章

错误只出现在发布模式而不是调试模式

VBA Excel 在调试中运行良好,但在安全更新 KB4022174 后无法在正常模式下运行

STM32调试模式下程序正常跑,下载后再跑没反应,何解?

Flutter:一个程序在调试模式下运行良好,但在发布后就不行,为啥?

C# WPF 应用程序在发布模式下失控,但不是调试模式

在调试模式下运行程序非常慢