I'm new to Qt and PyQt and I'm trying to connect an elaborate file parsing library written by someone else to a simple GUI. When I click on the "Process Data" button, I encounter the following error message repeatedly:
QCoreApplication::exec: The event loop is already running
QCoreApplication::exec: The event loop is already running
QCoreApplication::exec: The event loop is already running
QCoreApplication::exec: The event loop is already running
QCoreApplication::exec: The event loop is already running
...
I have noticed that when I debug the script, the issue doesn't occur if I put a breakpoint on the line sys.exit(app.exec_())
and only click on "Resume" after selecting the data. In this specific case, if I do this once and press "Resume" the program works in all subsequent attempts to load file(s) and folders.
Here is the relevant code:
import os
import sys
import traceback
import pandas as pd
import numpy as np
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QFileDialog, QTextEdit)
def ParsingFunction(directory=None, files=[], d_dataAlreadyIn=None):
# ...
# Import/outport function, mostly used for loading the .med files
from DC_Lib import DC_IO_lib
from DC_Lib import DC_CV_Processing
from DC_Lib import DC_IV_Processing
class DataProcessingApp(QWidget):
def __init__(self):
super().__init__()
# ...
self.process_button = QPushButton("Process Data")
self.process_button.clicked.connect(self.process_data)
self.layout.addWidget(self.process_button)
# ...
def process_data(self):
if self.directory or self.files:
self.text_edit.append("Processing data...")
if self.directory:
self.data = ParsingFunction(directory=self.directory)
else:
self.data = ParsingFunction(files=self.files)
self.text_edit.append("Data processing complete.")
else:
self.text_edit.append("Please select a directory or files to process.")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = DataProcessingApp()
window.show()
sys.exit(app.exec_())
If the question is too vague let me know, but I think this behavior with the exec_()
method during debugging might ring a bell to someone with more experience with Qt. Any insights or suggestions on how to resolve this issue would be greatly appreciated.
Thank you!
[update]
To improve reproducibility here are the contents of the ParsingFunction and its subfunctions. I won't add more code because I'm pretty sure the problem is with the input()
call in GetMeDopingType()
:
while True:
inp = str(input())
if inp.strip()[0].upper() == "C":
C_IO.Abort()
if inp.strip()[0].lower() == 'n' or inp.strip()[0].lower() == 'p':
break
GLOBAL_d_Dopingtypes[wafername] = inp.strip()[0].lower()
When I hardcode inp
, I don't get the QCoreApplication::exec
. Any ideas why not? This answer sounds like it has to do with my issue, but I haven't been able to translate into a fix for my case.
Here's the full code:
def ParsingFunction(directory=None, files=[], d_dataAlreadyIn=None):
AllData = {}
if d_dataAlreadyIn is not None:
AllData = d_dataAlreadyIn
WarnCount = 0
if directory is not None:
for root, dirs, files in os.walk(directory):
for filename in files:
WorkMagic_SubFunction(C_IO.EndInSlash(root), filename, AllData)
WarnCount += 1
if WarnCount % 100 == 0:
print(filename)
if WarnCount > 10000:
print("Warning: " + str(WarnCount) + " files processed, could indicate an infinite loop!")
else:
for file in files:
root = os.path.dirname(file)
filename = os.path.basename(file)
WorkMagic_SubFunction(C_IO.EndInSlash(root), filename, AllData)
WarnCount += 1
if WarnCount % 100 == 0:
print(filename)
if WarnCount > 10000:
print("Warning: " + str(WarnCount) + " files processed, could indicate an infinite loop!")
return AllData
def WorkMagic_SubFunction(directory, filename, AllData):
global DotArea
global ExtentionToLookFor
global INFER_PMA_FROM_FOLDER
extention = filename.split('.')[-1]
if extention == ExtentionToLookFor:
tmp = C_IO.ReadInMedFile(directory + filename, ForceReadSecondDataSection=HasToHandleBTI)
mestype = FigureOutWhatThisIs(tmp)
if 'SiP' in filename:
tmp["techinfo"]["doping"] = 'P'
if mestype == "DropThisOne":
return AllData
if INFER_PMA_FROM_FOLDER and "_PMA" in directory:
tmp["techinfo"]["wafer"] = tmp["techinfo"]["wafer"] + "A"
Device_ID = tmp["techinfo"]["testchip"] + "-" + tmp["techinfo"]["testdevice"]
if not "DotArea" in tmp["techinfo"]:
guessarr = FilenameToArea(filename)
if guessarr is None:
tmp["techinfo"]["DotArea"] = str(DotArea)
else:
tmp["techinfo"]["DotArea"] = str(guessarr)
else:
tmp["techinfo"]["DotArea"] = str(tmp["techinfo"]["DotArea"])
tmp["techinfo"]["ScriptName"] = str(SCRIPTNAME)
tmp["techinfo"]["ScriptVersion"] = str(VERSION)
if "devicemap" in tmp["techinfo"]:
tmp["techinfo"]["devicemap"] = tmp["techinfo"]["devicemap"].replace(r"/imec/other/drec/medusa", r"\\unix\drec\medusa")
if "chipmap" in tmp["techinfo"]:
tmp["techinfo"]["chipmap"] = tmp["techinfo"]["chipmap"].replace(r"/imec/other/drec/medusa", r"\\unix\drec\medusa")
key = tmp["techinfo"]["wafer"] + "___###____" + tmp["techinfo"]["chuck_temperature"]
if not key in AllData:
AllData[key] = {}
if not mestype in AllData[key]:
AllData[key][mestype] = {}
if not Device_ID in AllData[key][mestype]:
AllData[key][mestype][Device_ID] = []
finalStruct = None
if not (mestype == "NBTI" or mestype == "PBTI"):
if HasToHandleBTI:
techinfo = tmp["techinfo"]
# call to the input()
dop = GetMeDopingType(techinfo["wafer"], techinfo)
techinfo['doping'] = dop
tmp = C_IO.ReadInMedFile(directory + filename, ForceReadSecondDataSection=False)
tmp["techinfo"] = techinfo
if mestype == "MFCV":
finalStruct = tmp
elif mestype == "Hys":
TheStruct = C_CV.CV_HYS_Curve(SampleName=tmp["techinfo"]["wafer"], DopingType=GetMeDopingType(tmp["techinfo"]["wafer"], tmp["techinfo"]), Temperature_K=300)
TheStruct.Load___read_in_Med_structure(tmp)
TheStruct.do_areanormalisation(1.0)
finalStruct = TheStruct
elif mestype == "NBTI" or mestype == "PBTI":
TheStruct = C_CV.SFCV()
TheStruct.Load___read_in_Med_Structure(tmp)
TheStruct.do_areanormalisation(1.0)
finalStruct = TheStruct
elif mestype == "IgVg":
TheStruct = C_IV.SFIV()
TheStruct.Load___read_in_Med_Structure(tmp)
finalStruct = TheStruct
elif mestype == "CET":
TheStruct = C_CV.SFCV()
TheStruct.Load___read_in_Med_Structure(tmp)
finalStruct = TheStruct
else:
print("Mestype not supported! '" + str(mestype) + "' in file:" + directory + filename)
if not finalStruct is None:
if not type(finalStruct) is dict:
dop = GetMeDopingType(tmp["techinfo"]["wafer"], tmp["techinfo"])
finalStruct._header['doping'] = dop
AllData[key][mestype][Device_ID].append(finalStruct)
return AllData
# The function I think is causing the problem
def GetMeDopingType(wafername, techinfo):
global GLOBAL_d_Dopingtypes
if "SiP" in wafername:
return "p"
if not wafername in GLOBAL_d_Dopingtypes:
if techinfo is not None and "doping" in techinfo:
GLOBAL_d_Dopingtypes[wafername] = techinfo["doping"].strip()[0].lower()
else:
print("Please prodide doping type for wafer: " + str(wafername) + " [n/p]: ")
while True:
inp = str(input())
if inp.strip()[0].upper() == "C":
C_IO.Abort()
if inp.strip()[0].lower() == 'n' or inp.strip()[0].lower() == 'p':
break
GLOBAL_d_Dopingtypes[wafername] = inp.strip()[0].lower()
return GLOBAL_d_Dopingtypes[wafername]
def FilenameToArea(filename):
global ScannedSquareSizes_in_um
size = None
for i in ScannedSquareSizes_in_um:
if "_" + str(i) + "x" + str(i) + "_" in filename:
size = (float(i) * 1E-4) ** 2
break
return size
def FigureOutWhatThisIs(d_info):
if "targetrole" in d_info["techinfo"]:
TarRol = d_info["techinfo"]["targetrole"]
if TarRol == "VFBTEST":
return "DropThisOne"
elif TarRol == "CET_EXTRACTION" or TarRol == "REFERENCE":
return "CET"
elif TarRol == "FREQ_DISPERSION":
return "MFCV"
elif TarRol == "PBTI_MES" or TarRol == "PBTI_Reference" or TarRol == "PBTI_REFERENCE" or TarRol == "PBTI_AFTERCHECK":
return "PBTI"
elif TarRol == "NBTI_MES" or TarRol == "NBTI_Reference" or TarRol == "NBTI_REFERENCE" or TarRol == "NBTI_AFTERCHECK":
return "NBTI"
elif TarRol == "CVHYS":
return "Hys"
elif TarRol == "IgVg_leakage":
return "IgVg"
else:
print("Unknown target role:" + str(TarRol))
input("just hit enter to continue")
return "TechniqueNotKnown"
if "instrument" in d_info["techinfo"]:
if "Keithley Instruments" in d_info["techinfo"]["instrument"]:
return "IgVg"
if "filename" in d_info["techinfo"]:
tmp = d_info["techinfo"]["filename"]
if "Vmax" in tmp and not "_f" in tmp:
return "Hys"
if not "Vmax" in tmp and "_f" in tmp:
return "MFCV"
return "TechniqueNotKnown"
Regarding the debugging information I'm using Python 3.7.4 in a venv because part of the project has a dependency on PySide2.