-1

I'm making a calender using pyqt5, and it gives me this error when I Wrote these lines of code: from pyqt5 import QtCore, QtGui, QtWidgets, uic, and delclass = uic.loaduiType.

Traceback (most recent call last):
  File "C:\Users\hungy\Desktop\Mason Works\Python\Projects\Calender.py", line 7, in <module>
    delclass = uic.loadUiType('Del_btn.ui')
  File "C:\Users\hungy\AppData\Local\Programs\Python\Python39\lib\site-packages\PyQt5\uic\__init__.py", line 204, in loadUiType
    exec(code_string.getvalue(), ui_globals)
  File "<string>", line 5
    def setupUi(self, del):
                      ^
SyntaxError: invalid syntax

What's wrong with my code? I tried Changing the name to Delclass, but that didn't work. This is my code:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets, uic

# defines the formclasses
calclass = uic.loadUiType("Calender.ui")[0]
addclass = uic.loadUiType('Add_btn.ui')
delclass = uic.loadUiType('Del_btn.ui')
editclass = uic.loadUiType('Edit_btn.ui')
# classes
class Add(QtWidgets.QMainWindow, addclass):
    def __init__(self, parent=None):
        QtWidgets.QMainWindow.__init__(self, parent)
        self.setupUi(self)
        # self.Namevalue = Name_Text.value

class Calender(QtWidgets.QMainWindow, calclass):
    def __init__(self, parent=None):
        QtWidgets.QMainWindow.__init__(self, parent)
        self.setupUi(self)
        self.Add.triggered.connect(self.add_clicked)
        self.Delete.triggered.connect(self.del_clicked)
        self.Close_Exit.triggered.connect(self.x_clicked)

    def x_clicked(self):
        self.close()

    def del_clicked(self):
        pass

    def add_clicked(self):
        pass

app = QtWidgets.QApplication(sys.argv)
Window = Calender()
Window.show()
app.exec_()

.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>del</class>
 <widget class="QDialog" name="del">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>355</width>
    <height>106</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Del</string>
  </property>
  <property name="sizeGripEnabled">
   <bool>false</bool>
  </property>
  <widget class="QDialogButtonBox" name="OKCANCEL">
   <property name="geometry">
    <rect>
     <x>-80</x>
     <y>60</y>
     <width>341</width>
     <height>32</height>
    </rect>
   </property>
   <property name="orientation">
    <enum>Qt::Horizontal</enum>
   </property>
   <property name="standardButtons">
    <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
   </property>
  </widget>
  <widget class="QPushButton" name="Why">
   <property name="geometry">
    <rect>
     <x>10</x>
     <y>10</y>
     <width>93</width>
     <height>28</height>
    </rect>
   </property>
   <property name="text">
    <string>Why:</string>
   </property>
  </widget>
  <widget class="QPlainTextEdit" name="plainTextEdit">
   <property name="geometry">
    <rect>
     <x>120</x>
     <y>10</y>
     <width>191</width>
     <height>31</height>
    </rect>
   </property>
  </widget>
 </widget>
 <resources/>
 <connections>
  <connection>
   <sender>OKCANCEL</sender>
   <signal>accepted()</signal>
   <receiver>del</receiver>
   <slot>accept()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>248</x>
     <y>254</y>
    </hint>
    <hint type="destinationlabel">
     <x>157</x>
     <y>274</y>
    </hint>
   </hints>
  </connection>
  <connection>
   <sender>OKCANCEL</sender>
   <signal>rejected()</signal>
   <receiver>del</receiver>
   <slot>reject()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>316</x>
     <y>260</y>
    </hint>
    <hint type="destinationlabel">
     <x>286</x>
     <y>274</y>
    </hint>
   </hints>
  </connection>
 </connections>
</ui>
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Mason Lin
  • 29
  • 4
  • 1
    You're showing us an error about `del`, not `delclass`. If you still have an error with `delclass` and no further uses of `del`, _show us that error instead_ -- because `del` is a keyword (and so expected to fail when used in a conflicting way), but `delclass` is not. – Charles Duffy Aug 03 '21 at 22:32
  • 1
    `delclass = uic.loaduiType` is not the problem. `def setupUi(self, del):` is the problem. – Charles Duffy Aug 03 '21 at 22:34
  • I didn't write the def `setupUi(self, del):`. I imported pyqt5. – Mason Lin Aug 03 '21 at 22:36
  • It doesn't matter if you wrote it. That line _is_ the problem. – Charles Duffy Aug 03 '21 at 22:37
  • From the look of your code you probably created the `Del_btn.ui` by renaming the top level widget as `del`. While this would not result in a "practical" problem, it would become for Python, as `uic` would try to create a form class that would use `del` as argument of `setupUi`. This is not allowed, since `del` is a reserved word. Please open that UI file in Designer and rename that top level widget with another and more significative name than "del" (which is a very bad choice for naming). – musicamante Aug 03 '21 at 22:38
  • 1
    I'm voting to reopen this question: while the `del` duplicated answers are valid, they don't cover the problem of using protected keywords in Qt Designer, which has no knowledge of the possible usage and partial limitations of PyQt (and python) for the UI names. – musicamante Aug 03 '21 at 22:40
  • I changed my name to this, but it still gives me the error: `Dclass` – Mason Lin Aug 03 '21 at 22:42
  • @MasonLin please share the Del_btn.ui content – eyllanesc Aug 03 '21 at 22:43
  • This Question is full of typo, the title says *Why Can't I use the varible name delclass?*, but the error OP has mentioned is regarding `del` `SyntaxError: invalid syntax`. That's why I initially marked as duplicate for `del` – ThePyGuy Aug 03 '21 at 22:45
  • @ThePyGuy, ...that's the OP misunderstanding, assuming that the problem must be in their own code, rather than in code that uic generated and eval'd. Part of our purpose is to identify and correct such misunderstandings. – Charles Duffy Aug 03 '21 at 22:48
  • I'll write the ui file on an answer because it's too long. – Mason Lin Aug 03 '21 at 22:48
  • @CharlesDuffy, Yes, you are right ! – ThePyGuy Aug 03 '21 at 22:49
  • 1
    @ThePyGuy 1) It seems the OP never wrote that, at least it doesn't show it in the code. 2) I can't reproduce the problem so probably if the OP doesn't provide an MRE then the best shutdown reason is "typo or not reproducible". – eyllanesc Aug 03 '21 at 22:49
  • did you see the UI file? – Mason Lin Aug 03 '21 at 23:19
  • @eyllanesc, did you see the `Del_btn.ui` file?? – Mason Lin Aug 04 '21 at 14:43
  • And I changed it's name to `D_btn.ui`. – Mason Lin Aug 04 '21 at 14:44

2 Answers2

3

From the look of your code, you probably renamed the top level widget in Qt Designer as del.

While this doesn't represent a real problem from the Qt perspective, it can become such when using uic functions, which build a raw python file (or an "abstract" form of it) when using loadUiType.

uic (and pyuic, which uses the same functions) creates functions and objects based on the object names of the UI. Among these, there are:

  • def setupUi(self, <object name of the form>);
  • def retranslateUi(self, <object name of the form>);

The result is that if you name del your top level object, the functions will be:

  • def setupUi(self, del);
  • def retranslateUi(self, del);

This will obviously cause an exception, since del cannot be used like that in python.

Be aware that the same is valid for all other python protected words:

  • exec (while this is not an issue anymore in recent python versions, it's still better to avoid it, similarly to print)
  • raise, assert
  • def, class
  • if, elif, else, not
  • for, while
  • continue, break
  • try, except, finally
  • etc...

The solution (which is valid in any case) is to carefully choose object names: look for descriptive names, not short names, as they don't have any practical benefit.
Instead of del, prefer delButton (or del_button, if you want to keep the standard Python style), or deleteButton.

Remember: the name reference (or object name in Qt) of an object should always allow you to tell at a glance what that object is and what it does.
What does "del" do? Delete? Delete what? Is it a function or a variable? Is it a widget? If it's a widget, what kind of widget is it?

Reopen the UI file in Designer and change the name of the top level object accordingly, and also ensure that no other widget uses those protected names, because they would throw an exception in any case (for instance, you cannot have an object named self.raise).

musicamante
  • 41,230
  • 6
  • 33
  • 58
  • 1
    This is really a minor bug in Designer. It's actually impossible to use names like `if`, `else`, `for`, `break`, etc because those are C++ reserved keywords. Designer automatically munges such names by adding a suffix, so it could optionally include all the other Python keywords as well (i.e. as a preference or form setting). The uic tool can already generate Python code (which is viewable in Designer) so this really should be supported. – ekhumoro Aug 03 '21 at 23:40
  • @musicamante But I can't see the `def setupUi(self, del)` because I imported pyqt5. – Mason Lin Aug 04 '21 at 14:57
  • @MasonLin Please read my answer more carefully: you cannot "see" those functions, they are *internally* created by `uic.loadUiType`. And, in any case, that doesn't matter: the important thing is that you should **NOT** call an object "del", not in python, nor in Qt Designer. – musicamante Aug 04 '21 at 14:59
  • If you want to see it, just run `pyuic Del_btn.ui -o output.py` from the terminal/prompt (if required, change `pyuic` with what you've on your system, depending on the OS and PyQt versions installed it could be: `pyuic5`, `pyuic5.bat`, etc). Then you'll see those `def setupUi(self, del)` in the output file. – musicamante Aug 04 '21 at 15:04
  • @MasonLin What do you mean with "I can't edit"? – musicamante Aug 04 '21 at 15:18
  • So do you want me to change the name of my varible name and qt designer widgets? – Mason Lin Aug 04 '21 at 15:20
  • I meant like I can't make it(the qt code) change. – Mason Lin Aug 04 '21 at 15:22
  • @MasonLin that's exactly what explained in my whole answer, and what you must do is specifically written in the final paragraph of my answer: open again the ui files in Designer and change all names that are not appropriate for python. Please, if English is not your first language, try to find somebody who can help you to translate. Sorry, but the phrase "I can't make it(the qt code) change." doesn't mean anything. Try to make yourself clear. – musicamante Aug 04 '21 at 15:25
  • In my qt file, I don't have anything named as python keywords. – Mason Lin Aug 04 '21 at 15:31
  • I changed my varible name to `deleteclass`, but it still gives me an error. – Mason Lin Aug 04 '21 at 15:34
  • @MasonLin Yes, you have, in the file you shared the *top level* widget (the QDialog) is named `del`. Open that "Del_btn.ui" file in Designer, look in the top left of the "Object Inspector" and you'll see it. Otherwise, just click on an empty space of that dialog, outside any button or label, and look at the "Property Editor", the object name (the top field) will show you `del`. You need to change that, *save* the file and then recheck your script (note that you have other problems in your code, but they're off topic for this question and will not be addressed here). – musicamante Aug 04 '21 at 15:35
  • but then I changed it to `button` – Mason Lin Aug 04 '21 at 15:37
  • `button - delete_button` – Mason Lin Aug 04 '21 at 15:38
  • `Traceback (most recent call last): File "C:\Users\hungy\Desktop\Mason Works\Python\Projects\Calender.py", line 7, in deleteclass = uic.loadUiType('delete_button.ui') File "C:\Users\hungy\AppData\Local\Programs\Python\Python39\lib\site-packages\PyQt5\uic\__init__.py", line 204, in loadUiType exec(code_string.getvalue(), ui_globals) File "", line 5 def setupUi(self, del): ^ SyntaxError: invalid syntax ` – Mason Lin Aug 04 '21 at 15:41
  • According to that error, you didn't rename the dialog in Designer, you only renamed the file (or you're not using the one you've modified in Designer). – musicamante Aug 04 '21 at 15:43
  • I think I forgot to save it, so it doesn't update the name. But then I saved it and it still give me that Error(^) – Mason Lin Aug 04 '21 at 15:47
  • As already said, if you still get that error, it means that you're still using the previous file or you didn't properly rename the top level QDialog, since that error clearly says that the file 'delete_button.ui' **still* uses "del" for the object name. – musicamante Aug 04 '21 at 15:53
  • Now it works, but then it gives me *this* error: `Traceback (most recent call last): File "C:\Users\hungy\Desktop\Mason Works\Python\Projects\Calender.py", line 10, in class Add(QtWidgets.QMainWindow, addclass): TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases` – Mason Lin Aug 04 '21 at 21:26
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/235636/discussion-between-mason-lin-and-musicamante). – Mason Lin Aug 04 '21 at 21:32
  • @MasonLin as said, there are other problems in your code. In this specific case you forgot the `[0]` at the end of all the other `loadUiType`; as the [documentation explains](https://riverbankcomputing.com/static/Docs/PyQt5/api/uic/uic-module.html#loadUiType), it returns "a tuple of the generated *form class* and the *Qt base class*", which obviously creates a problem for the inheritance: `addclass` is a *tuple*, while the class expects a *form class* to inherit from. You either add `[0]` at the end of *all* those lines, or you use `uic.loadUi("path.ui", self)` in the `__init__` of each class. – musicamante Aug 04 '21 at 21:53
  • @MasonLin then I suggest you to mark this answer as accepted, since it solved your problem. For future reference, please **always** ensure that you properly follow instructions that are given to you, and whenever you have get an error don't just tell us "it gives me an error", otherwise we (you and us) will only lose a lot of time and unnecessary comments that could be avoided if you just tell us the error in the first place. – musicamante Aug 05 '21 at 17:36
0

del is a reserved word in python. It deletes an object with del x.

For example:

>>> x = 5
>>> x
5
>>> del x
>>> x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined