I have googled so much about this but did not find anything..
I have a custom exception class which invoked a QDialog to show the warning message..Now i am writing test for my application and in the test, i am sending the data which will make the application raise that exception and hence the dialog will appear.
But when i am running the test using pt.test, the dialog is appearing and when i close it, this is printed on my console..
E Failed: DID NOT RAISE
apptest.py:31: Failed
----------------------------- Captured stderr call -----------------------------
Traceback (most recent call last):
File "/home/kapil/mp3wav/mp3wav/application.py", line 62, in <lambda>
self.connect(self.conversionButton, SIGNAL("clicked()"), lambda: self.startConversion())
File "/home/kapil/mp3wav/mp3wav/application.py", line 79, in startConversion
self.__convert()
File "/home/kapil/mp3wav/mp3wav/application.py", line 86, in __convert
self.checkFile(__OUTFILE)
File "/home/kapil/mp3wav/mp3wav/application.py", line 105, in checkFile
raise FileTypeException(fileType, self)
mp3wav.exceptions.fileexception.FileTypeException
This is my test file..
import pytest
import os
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from mp3wav.application import Mp3WavApp
from mp3wav.exceptions.fileexception import FileTypeException
from mp3wav.exceptions.libraryexception import LibraryException
from mp3wav.exceptions.filenotexistexception import FileNotExistException
from mp3wav.exceptions.samefileexception import SameFileException
from mp3wav.exceptions.overwriteexception import OverWriteException
def windowTest(qtbot):
testapp = Mp3WavApp()
testapp.show()
qtbot.addWidget(testapp)
assert testapp.isVisible()
assert testapp.close()
#pytest.mark.qt_no_exception_capture
def fileTypeTest(qtbot, tmpdir):
testapp = Mp3WavApp()
qtbot.addWidget(testapp)
infile = tmpdir.mkdir("files").join("demo.mp3")
infile.write("something")
testapp.inputFileLine.setText(str(tmpdir.join("files", "demo.mp3")))
testapp.outputFileLine.setText(str(tmpdir.join('files')))
testapp.outputFileLineName.setText('demo.wave')
with pytest.raises(FileTypeException) :
qtbot.mouseClick(testapp.conversionButton, Qt.LeftButton)
Here is the custom exception
import os
import sys
from mp3wav.exceptions.errordialog import ErrorDialog
class FileTypeException(Exception):
def __init__(self, sid, parent=None):
super(FileTypeException, self).__init__()
filetype = "mp3"
if sid==2:
filetype = "wav"
errorMessage = "The Selected file is not "+filetype+\
"\nSelect the appropriate file"
if parent:
dialog = ErrorDialog(parent, errorMessage)
dialog.show()
dialog.exec_()
else:
print(errorMessage)
What i think is that it is failing because the dialog is appearing during the run of my test and i need to close it manually..But i don't know exactly why the test is failing..
Can anyone please guide me to the right path.. It will very much be appreciated..
Related
I'm writing a code on PyCharm, but it is easier for me if I could debugg continually while I'm writing my code. I can't figure out, that how do I get this class debugged? :
from PyQt5.Qt import QGraphicsPixmapItem
from PyQt5.QtGui import QPixmap
class Level():
def __init__(self, scene, level):
self.scene = scene
self.level = open(level)
def add_item_to_scene(self):
for x in range(self.level):
for y in range(self.level[0]):
if y == 'X':
brick = QPixmap('brick.png')
self.scene.addItem(brick)
I have just begun and this is all what I've written. I'm doing a Platformer game with PyQt5, and I'm trying to set the levels now. Thank you for any help.
Use a convention to run code during development and not run the code on import as shown in the following code.
from PyQt5.Qt import QGraphicsPixmapItem
from PyQt5.QtGui import QPixmap
class Level():
def __init__(self, scene, level):
self.scene = scene
self.level = open(level)
def add_item_to_scene(self):
for x in range(self.level):
for y in range(self.level[0]):
if y == 'X':
brick = QPixmap('brick.png')
self.scene.addItem(brick)
# Use the following convention.
# In python the initial module run receives the name __main__.
if __name__ == '__main__':
print(f'Hello my name is {__name__=} because my module was started by '
f'pyhton. ')
# So while developing whenever you run this module commands here will run.
# Later on when you import the module the commands will not run.
# because __main__ will be the name of this module
l = Level('brick', 5)
l.add_item_to_scene()
else:
# Place any commands you want to run on import here.
print(f'Hello my name is {__name__=} because my module was imported by '
f'another module. ')
Demo Results:
If run directly from python
Hello my name is __name__='__main__' because my module was started by pyhton.
Traceback (most recent call last):
File "C:\Users\ctynd\OneDrive\CodeBase\StackOverflowActivity\OldScratches\scratch_2.py", line 27, in <module>
l = Level('brick', 5)
File "C:\Users\ctynd\OneDrive\CodeBase\StackOverflowActivity\OldScratches\scratch_2.py", line 9, in __init__
self.level = open(level)
OSError: [WinError 6] The handle is invalid
If imported:
import scratch_2
Results
Hello my name is __name__='scratch_2' because my module was imported by another module.
an update to my code, based on the reply of Israel Unterman:
The Error-Class is now
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QMainWindow
class Error(QtWidgets.QMainWindow):
reply = False
last_reply_id = None
last_id = 0
def __init__(self, error_code_string, parent=None):
super().__init__(parent)
QtWidgets.QMessageBox.warning(self, "Warnung", error_code_string, QtWidgets.QMessageBox.Ok)
id = give_id(self)
def give_id(self):
self.last_id += 1
return self.last_id
def give_reply(self):
if last_id == last_reply_id:
return self.reply
else:
return None
def set_reply(self, button, id):
if button in (QMessageBox.Ok, QMessageBox.Yes):
reply = True
else:
reply = False
self.last_reply_id = id
return reply
And the Test-Script comes with
from ErrorHandling import Error
Error('Test')
If I am using the normal Code (practically the same Code, just wrapped in a class) the message appears and then at the line
id = give_id(self)
the Code stops without any errormessage from python, just:
Process finished with exit code 1
If I use the test-script, there is nothing (No QMessageBox!) than this:
Process finished with exit code 1
If I debug the Code, init() gets the same Objects and variables, but
super().__init__(parent)
fails without any message.
So where is the mistake, or difference.
Here a shortend Version of the Class (it's too long to show all code here), from which the "Error" works nearly fine:
from ErrorHandling import Error
class MainWindow(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
# set some variables
self.create_layout()
def create_layout(self):
# creates a GUI using QWidgets with some Inputboxes and one button
[...]
def button_start_clicked(self):
Error('Check the input')
Here is the old question:
I have a problem regarding the setup of QtWidgets.QMessageBox.
All Code follows the description.
The ErrorHandling-Modul should give a message about an error.
If needed it may ask a question too.
The function ErrorMsg.errorMessage is called from other Moduls in case of an catched exception.
There will be more functions added.
If I run the code the following error occurs:
Connected to pydev debugger (build 145.1504)
Traceback (most recent call last):
File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 2016.1.4\helpers\pydev\pydevd.py", line 1531, in <module>
globals = debugger.run(setup['file'], None, None, is_module)
File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 2016.1.4\helpers\pydev\pydevd.py", line 938, in run
pydev_imports.execfile(file, globals, locals) # execute the script
File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 2016.1.4\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "C:/Quellcode/AllgTest.py", line 5, in <module>
reply = errm.errorMessage('Test')
File "C:/Quellcode\ErrorHandling.py", line 20, in errorMessage
msg_box.setIcon(QMessageBox.Warning)
TypeError: QMessageBox.setIcon(QMessageBox.Icon): first argument of unbound method must have type 'QMessageBox'
Process finished with exit code 1
I tried quite some variations and googled, but I have no idea what the problem is since I found some examples that are using the line
QMessageBox.setIcon(QMessageBox.Icon)
So where is my mistake?
And now the Code:
There is the following testscript to test my ErrorMsg-class
from ErrorHandling import ErrorMsg
errm = ErrorMsg()
reply = errm.errorMessage('Test')
And here is my ErrorHandling-Modul
from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtWidgets import QMainWindow
class ErrorMsg(QMainWindow):
def __init__(self):
pass
def giveback(self,button):
if button in (QMessageBox.Ok, QMessageBox.Yes):
reply = True
else:
reply = False
return reply
def errorMessage(self, error_msg, buttons='OK'):
msg_box = QMessageBox
msg_box.setIcon(QMessageBox.Warning)
msg_box.setWindowTitle('Warning')
if buttons == 'OK':
msg_box.setStandardButtons(QMessageBox.Ok)
elif buttons == 'YesNo':
msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
else:
error_msg = 'Unknown Button >' + buttons + '<, use >OK< or >YesNo<'
raise ValueError(error_msg)
msg_box.setText(error_msg)
clicked_button = msg_box.exec()
return giveback(clicked_button)
Thanks for your help
James
You didn't create an object of the message box. To create an object use:
msg_box = QMessageBox()
But you don'y need to go through all this, since QMessageBox has static functions for showing messages, which you can call directly on the QMessageBox class. For example:
QMessageBox.warning(None, 'title', 'msg')
You also have some control over the butons, see QMessageBox
My PyQt application no longer prints the error (stderr?) to the console.
I use QtDesigner and import the UI like this:
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from PyQt5.uic import loadUiType
Ui_MainWindow, QMainWindow = loadUiType("test.ui")
class Main(QMainWindow, Ui_MainWindow):
"""Main window"""
def __init__(self,parent=None):
super(Main, self).__init__(parent)
self.setupUi(self)
self.pushButton.clicked.connect(self.testfunc)
def testfunc(self):
print(9/0)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
main = Main()
main.show()
sys.exit(app.exec_())
test.ui contains a QPushButton and a label. When I call testfunc (which obviously gives an error) in a non-Qt application, I get the error message, traceback, etc. When I execute this code, it just exits.
I wrote a PyQt application without QtDesigner before and it printed the errors to the console as expected. What's the difference with QtDesigner and inheritance?
This is probably due to changes in the way exceptions are dealt with in PyQt-5.5. To quote from the PyQt5 Docs:
In PyQt v5.5 an unhandled Python exception will result in a call to
Qt’s qFatal() function. By default this will call abort() and the
application will terminate. Note that an application installed
exception hook will still take precedence.
When I run your example in a normal console, this is what I see:
$ python test.py
Traceback (most recent call last):
File "test.py", line 213, in testfunc
print(9/0)
ZeroDivisionError: division by zero
Aborted (core dumped)
So the main difference is that the application will now immediately abort when encountering an unhandled exception (i.e. just like a normal python script would). Of course, you can still control this behaviour by using a try/except block or globally by overriding sys.excepthook.
If you're not seeing any traceback, this may be due to an issue with the Python IDE you're using to run your application.
PS:
As a bare minimum, the old PyQt4 behaviour of simply printing the traceback to stdout/stderr can be restored like this:
def except_hook(cls, exception, traceback):
sys.__excepthook__(cls, exception, traceback)
if __name__ == "__main__":
import sys
sys.excepthook = except_hook
I've been using python's traceback module in conjunction with a try/except statement to make sure the traceback is printed before exiting:
https://docs.python.org/3/library/traceback.html
Spefically, I use traceback.print_exc()
I'm trying to make a little pinging tool with Scapy and PyQt4.
The code is fairly simple and all it does now is pinging an address the user can type in.
from PyQt4 import QtGui
import sys
from scapy.all import *
from scapy.sendrecv import sr, send
def q2s(qstr): return "%s" %qstr
class Application(QtGui.QMainWindow):
def __init__(self):
super(Application, self).__init__()
self.resize(1000,500)
self.centre()
self.initGui()
self.show()
def initGui(self):
self.ipAddress = QtGui.QLineEdit("1.1.1.1",self)
self.label = QtGui.QLabel("...")
self.label.move(50,100)
pingBtn = QtGui.QPushButton("Ping!", self)
pingBtn.move(50,50)
pingBtn.clicked.connect(self.ping)
def ping(self):
ip = q2s(self.ipAddress.text())
ans, unans = sr(IP(dst=ip)/ICMP(), timeout=1, verbose=0)
if ans:
self.label.setText("Host is up")
else:
self.label.setText("Host is down")
def centre(self):
screen = QtGui.QDesktopWidget().screenGeometry()
sizeNow = self.geometry()
self.move((screen.width() - sizeNow.width()) / 2,
(screen.height() - sizeNow.height()) / 2)
def run():
app = QtGui.QApplication(sys.argv)
GUI = Application()
sys.exit(app.exec_())
run()
However, when trying to ping an IP address an error is printed to the console.
Traceback (most recent call last):
File "Application.py", line 71, in ping
ans, unans = sr(IP(dst=ip)/ICMP(), timeout=1, verbose=0)
File "/usr/lib/python2.7/dist-packages/scapy/sendrecv.py", line 317, in sr
a,b=sndrcv(s,x,*args,**kargs)
File "/usr/lib/python2.7/dist-packages/scapy/sendrecv.py", line 129, in sndrcv
inp, out, err = select(inmask,[],[], remaintime)
select.error: (4, 'Unterbrechung w\xc3\xa4hrend des Betriebssystemaufrufs')
The last line means something like "Interruption during call of operating system".
I can not see what might be wrong about the program.
Using the send function instead of the sr function works somehow. So I think the problem might be that the application is waiting for a response. But I still don't know how to fix the error.
It's a bug in Scapy: an exception we want to catch when calling select() is different when in multi-thread environment.
A pull-request (#417) is currently examined (I'll update this answer when it has been merged), so you can check if the patch fixes this issue for you (I hope so!).
I was coding in python and added Trace-backs for error handling.
For better understanding, lets say i have 3 classes.
C1 = Main Class
TraceBack = Other Class
My Main class will import other classes (TraceBack) and create instances of these class and proceeds as coded. For error handling i imported traceback module in all 3 classes and updated my code within try: except: Everything is working fine as desired.
Now i got an idea, to keep traceback only in main class. As other classes are imported in the main class.
my C1.py looks like below
import traceback
from TraceBack import C3
class tracebackTest():
def __init__(self):
try:
self.c3_Inst = C3(1,0)
self.c3_Inst.sub()
except Exception as ex:
TraceBk = traceback.format_exc()
print 'Error Raised from Trace Back\n%s' % TraceBk
if __name__ == '__main__':
import sys
from PyQt4 import QtGui
app = QtGui.QApplication(sys.argv)
win = tracebackTest()
sys.exit(app.exec_())
my TraceBack.py looks like below
from PyQt4 import QtGui
class C3(QtGui.QMainWindow):
def __init__(self,x,y):
super(C3,self).__init__()
self.a = x
self.b = y
button = QtGui.QPushButton('Test',self)
button.clicked.connect(self.sub)
self.show()
def sub(self):
result = self.a / self.b
print 'result %s' % result
In C1.py after creating instance i called self.c3_Inst.sub() immediately, which will give below trace back from the Exception.
Error Raised from Trace Back
Traceback (most recent call last):
File "D:\PBL_Data\Development\Showtime_Python\RnD\TraceBack_1a.py", line 25, in __init__
self.c3_Inst.sub()
File "D:\PBL_Data\Development\Showtime_Python\RnD\TraceBack.py", line 37, in sub
result = self.a / self.b
ZeroDivisionError: integer division or modulo by zero
But when i click the button in the window. I get below error, which is not raised from Exception in C1.py
Traceback (most recent call last):
File "D:\PBL_Data\Development\Showtime_Python\RnD\TraceBack.py", line 37, in sub
result = self.a / self.b
ZeroDivisionError: integer division or modulo by zero
Can any one tell me actual approach for trackback to work in the PyQt which are connected to widget signals.
By the time you click the button, Python is long past that try..except surrounding self.c3_Inst = C3(1,0). If you want to catch the exception in c1.py, you'd need to put the try..except around app.exec_().