Issue
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.
Solution
The input()
function within the GetMeDopingType()
function seems to cause conflicts with the event loop. When the script is running normally, the event loop is already active, so using input()
inside it triggers the error.
However, when you add a breakpoint on sys.exit(app.exec_())
and click "resume" after selecting the data, the event loop hasn't started yet when you reach the input()
call. That's why it works without any errors in that case.
A solution can be to modify your code to avoid using input()
within the event loop. Try, for example, to use a separate dialog or input box to gather user input instead of relying on console input.
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QLabel, QLineEdit, QPushButton, QApplication
# ...
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:
app = QApplication.instance()
dialog = QDialog()
layout = QVBoxLayout()
label = QLabel("Please provide doping type for wafer: " + wafername + " [n/p]:")
input_box = QLineEdit()
layout.addWidget(label)
layout.addWidget(input_box)
ok_button = QPushButton("OK")
ok_button.clicked.connect(dialog.accept)
cancel_button = QPushButton("Cancel")
cancel_button.clicked.connect(app.exit) # Abort the processing
layout.addWidget(ok_button)
layout.addWidget(cancel_button)
dialog.setLayout(layout)
dialog.setWindowTitle("Doping Type Input")
if dialog.exec_() == QDialog.Accepted:
inp = input_box.text()
if inp.strip()[0].upper() == "C":
C_IO.Abort()
GLOBAL_d_Dopingtypes[wafername] = inp.strip()[0].lower()
else:
C_IO.Abort()
return GLOBAL_d_Dopingtypes[wafername]
Answered By - semsaco
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.