#pyqt | Logs for 2020-06-11

Back
[00:09:39] -!- yustin has joined #pyqt
[00:23:20] <altendky> Welp, between pytest-twisted and Qt5Reactor it ended up creating two QtEventReactor instances. Not sure why it matters or why only with pyqt 5.15 but... Tests are passing again.
[00:50:56] <[Tritium]> uh... twisted doesn't like having 2 reactors, IIUC - they are supposed to be singletons
[00:51:11] <[Tritium]> "singletons" - globals
[00:52:30] <altendky> [Tritium]: it wasn't getting installed. Twisted stopped that. Pytest-twisted was catching the exception about it already being installed. But Qt5Reactor was still creating the object so it could pass it to twisted for installation that failed.
[00:52:57] <[Tritium]> ooooh. I didn't read back far enough then
[00:52:59] <[Tritium]> sorry
[00:53:07] <altendky> And it's very specifically an issue with PyQt5 5.15 on Windows.
[00:53:19] <altendky> Oh, I don't think I gave the whole story :]
[00:53:56] <altendky> Pyside2 is fine. Pyqt 5.14.2 is fine. Linux and macOS were fine
[00:54:20] <[Tritium]> I dont know if this is anathema for this channel, but do you know if the equivalent pyside 2 version exhibits the same behavior? ... apparently not!
[00:55:06] <altendky> Yeah, so that suggested it was likely not a change in qt itself
[00:55:28] <[Tritium]> ping riverbank with it if you can
[00:55:51] <altendky> If I bother to break it down I will.
[00:58:54] <altendky> Honestly my goal is to be using pyside2 (I'm not a gpl fan) and trio (twisted seems stagnant) for my 'next' application whenever that happens.
[01:01:51] <altendky> But, off to bed. One least bug on my list. Well, at least half off my list.
[01:32:56] -!- jmarsac has joined #pyqt
[01:38:41] yustin is now known as yustin_42
[03:30:16] -!- honigkuchen has joined #pyqt
[04:41:12] -!- BPL has joined #pyqt
[04:41:37] -!- SpinTronix has joined #pyqt
[05:27:55] -!- gadesantares has joined #pyqt
[05:29:29] <gadesantares> Hello all!!! Well I've direted here from a telegram group devoted to PySide... I have a module which also has a qt designer plugin. It used to work well, but I had to move to another machine and I get this error when running qtdesigner
[05:30:19] <gadesantares> TypeError: unable to convert a Python 'NoneType' object to a c++ 'int' instance
[05:31:00] <gadesantares> I'm running Qt 5.11.3 on a Debian 10 machine, PyQt5 version 5.11.3
[05:32:24] <gadesantares> Google search downs't help much. I guess somewhere there is a problem with tyoes conversion but the debug information is so simple that I'cant figure out what's going on. Any hints? Thanks in advance!!!
[05:40:17] <ali1234> it means instead of having an object, you have None, ie something didn't load properly
[05:40:46] <ali1234> it is not a problem with type conversion, you really can't convert None into an int
[05:41:11] <ali1234> further diagnosis will require the code and full traceback
[05:51:05] <gadesantares> So in this case, to get the traceback maybe I should install qt designer debugging symbols etc?
[05:53:32] <gadesantares> (by the way, ther's no dbg package for qt5 designer) How could I start to solve this?
[06:05:59] -!- jmarsac has quit [Read error: Connection reset by peer]
[06:07:54] -!- jmarsac_ has joined #pyqt
[06:52:20] <ali1234> just get a full python traceback
[06:52:31] <ali1234> it will have at least the line number where the error occured
[07:26:02] -!- thomasross has quit [Ping timeout: 256 seconds]
[07:26:58] <The-Compiler> ali1234: how would you get a full python traceback if none is printed?
[07:35:55] <ali1234> find the piece of code that says "except Exception as e: print(e)" and change it to "raise e"
[07:36:24] <The-Compiler> ali1234: that exception is coming from PyQt, not from gadesantares' code
[07:39:39] <ali1234> is it coming from a different thread?
[07:41:40] <The-Compiler> hard to tell without a stacktrace probably ;) But it does come from C++
[07:42:00] <ali1234> if it isn't in a different thread, and it isn't catchable from python code, then i consider it a bug in PyQt
[07:42:23] <ali1234> catching exceptions and printing a useless error message is bad
[07:42:53] <The-Compiler> Exceptions coming from e.g. C++ virtuals never have a Python stacktrace
[07:43:18] <ali1234> it doesn't matter, you would at least know what function it is
[07:45:09] <The-Compiler> nope - I've definitely seen exceptions like this coming from inside PyQt without a Python stacktrace
[07:45:44] <ali1234> i believe that, but i consider it to be a poor design
[07:46:46] <ali1234> if "TypeError: unable to convert a Python 'NoneType' object to a c++ 'int' instance" is really the only thing that gets printed and the program does not crash, that is as useless as printing nothing at all
[07:54:19] <altendky> Do we need an excepthook?
[07:56:12] <altendky> gadesantares: what os are you in? I did add an exception dialog to designer in PyQt5-tools. I forget if I got it added back with the new builds. :| I'm also not totally sure if it would help or not here.
[08:02:08] <altendky> mm, nevermind, probably not relevant.
[08:04:19] <altendky> ali1234: it's a pain, but not as useless as nothing. but if it's all in c++ and python c-api code then yeah, there's no python stack. but sure, there might be some way to present more info. doesn't seem like this is coming from python code so it's not a matter of 'print(e)' being the problem.
[08:04:44] -!- bomex has joined #pyqt
[08:05:01] <bomex> hello
[08:05:11] <bomex> I have an issue with my QThread
[08:05:37] <bomex> after I quit my app, I get this error message: QThread: Destroyed while thread is still running
[08:05:51] <bomex> how can I fix that?
[08:09:32] <ali1234> call wait() on it before exiting the program
[08:09:52] <ali1234> make sure that there is some mechanism for it to stop running though, otherwise it will just wait forever
[08:10:42] <altendky> bomex: you might have to share code. there are various ways to use QThreads
[08:12:11] <The-Compiler> gadesantares: I wonder if you could run qtdesigner inside gdb and break on PyErr_Format
[08:12:14] <bomex> do you have any example for this?
[08:12:28] <altendky> bomex: an example of sharing your code? :]
[08:12:38] <The-Compiler> gadesantares: though to make that work, debugging symbols for Python is probably more important than those for Qt Designer
[08:12:56] <bomex> no, an example of how a QThread can be properly stopped
[08:13:29] <bomex> I found many examples that don't work or crash my app
[08:14:12] <bomex> ali1234: so I wait() on a thread and then what?
[08:14:26] <altendky> bomex: right, it depends how you use it. there are multiple ways. share your code
[08:14:41] <ali1234> that's it. the program won't exit until the thread stops running, and you won't see that error message :)
[08:14:54] <altendky> and the thread won't stop running until... well, it depends.
[08:15:31] <ali1234> typically you use some thread safe object like a mutex to tell the thread to exit
[08:15:40] <ali1234> then you wait on it
[08:16:06] <ali1234> but it depends what your thread actually does
[08:17:15] <bomex> shall I use signals and slots to connect a QThread's finished signal and connect that to a slot, perhaps to a .deleteLater of QObject?
[08:18:46] <altendky> bomex: who knows. if you don't know despite having your code... it's reasonable that we might not know never having seen your code.
[08:19:03] <ali1234> pointless if there is no mechanism for the thread to finish
[08:19:04] <altendky> the point of coming here is to bring our knowledge and your code together to address the situation.
[08:27:39] <bomex> my code: https://pastebin.com
[08:28:25] <bomex> that's the board.py module of my app
[08:28:42] <bomex> that's where all the relevant code is
[08:30:23] <bomex> so, take a look at my code and tell me how can I make a clean exit out of the app without that annoying error message about QThread being destroyed while still running
[08:35:29] <The-Compiler> bomex: add a closeEvent for Chessboard and call self.background_process.quit() and .wait() from there
[08:36:14] <bomex> does the QSvgWidget even have a closeEvent?
[08:36:38] <ali1234> yes
[08:36:47] <bomex> okay, lemme get hackin'
[08:36:48] <The-Compiler> it inherits QWidget, so yes
[08:36:54] <ali1234> exactly
[08:39:17] <bomex> The-Compiler: do I just put self.background_process.quit() in the closeEvent or do I need to use signals and slots for that?
[08:42:54] <bomex> self.background_process.quit() emits a 'finished' signal... is that correct?
[08:43:47] <The-Compiler> right
[08:44:26] <bomex> since that is the case, then I can simply do something like this: self.background_process.finished.connect(self.engine.deleteLater)
[08:45:23] <bomex> self.engine is an instance of my QObject subclass where all the chess engine processing is done
[08:45:26] <The-Compiler> you already do that in the code you pasted?
[08:45:35] <The-Compiler> sounds reasonable, yeah
[08:45:49] <bomex> but it does not work :/
[08:46:00] <The-Compiler> what does "does not work" mean precisely?
[08:46:16] <bomex> it means I get the same error message
[08:46:52] <The-Compiler> so, how are you quitting your application?
[08:46:57] -!- jmarsac has joined #pyqt
[08:46:59] <The-Compiler> is that closeEvent getting called?
[08:48:11] <bomex> it should have when the close event of the main window is accepted
[08:49:00] <bomex> I have a mainwindow.py module where a have a QMainWindow subclass
[08:49:05] <altendky> emitting a signal to another thread doesn't mean that it will finish before the main thread does. hence waiting, right? perhaps we should see the modified code?
[08:49:38] <bomex> yeah, lemme repaste
[08:50:47] -!- jmarsac_ has quit [Ping timeout: 272 seconds]
[08:53:12] <bomex> https://pastebin.com
[08:54:17] <altendky> bomex: you aren't waiting, i think the suggestion included waiting
[08:56:12] <bomex> well, I quit() the QThread instance (which emits a'finished' signal), and I connect that 'finished' signal to the QObject's deleteLater() slot
[08:56:33] <ali1234> yes but you didn't wait
[08:56:37] <bomex> is that all that is needed?
[08:56:41] <ali1234> you always have to wait on threads
[08:57:01] <ali1234> the syscall is badly named. it does not just wait, it also does teardown
[08:57:06] <ali1234> you can thank unix for that
[08:57:07] <bomex> so I need to put something else inside the closeEvent in my QSvgWidget subclass?
[08:57:54] <bomex> or just .wait() ?
[08:58:17] <bomex> self.background_process.quit()
[08:58:20] <bomex> and
[08:58:28] <bomex> self.background_process.wait()
[08:58:31] <bomex> ???
[08:58:37] <ali1234> sounds reasonable
[08:59:37] <bomex> ali1234: by "teardown" you mean it also does the same thing as the .quit() ??
[08:59:41] <ali1234> no
[08:59:55] <bomex> i see
[09:00:05] <bomex> one more thing... does the order matter?
[09:00:13] <ali1234> i don't know exactly what happens in Qt but threads in general are on OS function that is usually at least inspired by unix
[09:00:18] <ali1234> yes the order matters
[09:00:31] <bomex> first .quit() and then .wait() ??
[09:00:34] <ali1234> you tell the thread to quit() in some way, then you wait() for it to actually quit
[09:00:35] <bomex> or vice versa?
[09:00:47] <bomex> i see
[09:00:51] <ali1234> because it is a thread, it may take some time before it receives the message and quits
[09:01:15] <ali1234> wait() waits for it to finish and collects the exit code
[09:02:08] <ali1234> if you do not wait() on a thread, it does not actually terminate. it becomes a zombie. at least, on unix
[09:02:26] <bomex> but that's needed that QThread's 'finished' signal is connected to the QObject's 'deleteLater()' slot? right?
[09:02:41] <ali1234> i have no idea what that does
[09:02:59] <altendky> i wouldn't have started with that no. just make sure it quits and wait for it to finish quitting.
[09:03:00] <bomex> I found this in a forum
[09:03:49] <altendky> i'd drop it for now. see if it can work cleanly without that
[09:04:24] <bomex> since .quit() emits the 'finished' signal, I could connect that to .wait() ?
[09:05:21] <bomex> self.background_process.finished.connect(self.background_process.wait)
[09:05:27] <ali1234> technically i guess you could do that but then your program won't actually wait for wait to run and you may still get the error
[09:05:44] <ali1234> unless Qt guarantees that all signals get handled before exit, but i dont think it does
[09:05:47] <bomex> well, I do call .quit() inside the closeEvent
[09:05:59] <ali1234> just call wait manually
[09:06:04] <bomex> okay
[09:07:14] <bomex> still getting the same error message
[09:07:54] <bomex> def closeEvent(self, event): self.background_process.quit() self.background_process.wait()
[09:08:02] <bomex> that's my code now
[09:08:15] <bomex> and it fails
[09:08:25] <ali1234> ehhhh... i'm just guessing now but try wait() before quit()
[09:08:31] <ali1234> will probably make the program hang
[09:08:57] <bomex> maybe I need to put that code into the QMainWindow's closeEvent ??
[09:09:26] <ali1234> hmm
[09:09:27] <bomex> and not inside QSvgWidget's closeEvent ?
[09:09:36] <ali1234> not really
[09:09:43] <ali1234> and you should call quit before wait
[09:09:50] <ali1234> but maybe your thread doesn't have an event loop
[09:10:00] <bomex> it does
[09:10:29] <ali1234> i haven't enough experience using threads in Qt to suggest anything at this point
[09:10:29] <bomex> QObject has an event loop
[09:10:39] <bomex> that's a fact
[09:10:52] <bomex> QRunnable, on the other hand, does not have an event loop
[09:11:15] <altendky> bomex: always share full modified code and output
[09:11:19] <bomex> I've read 1000 things on this topic and can't get that damn QThread to die
[09:11:26] <bomex> and die properly
[09:11:35] <altendky> QObject doesn't have an event loop. a QThread might
[09:11:52] <altendky> bpaste.net/+pytb+python
[09:11:58] <bomex> or is the other way around
[09:12:15] <bomex> I'm kinda frustrated right now and can't recall what the forum said
[09:12:41] <bomex> anyway, lemme try this and that and hopefully it'll work
[09:12:44] <altendky> forget the forum for now
[09:18:30] <ali1234> "QJSValue does not support item assignment" wat
[09:20:37] <bomex> dumb threads!
[09:20:45] <bomex> nothing works
[09:22:28] <bomex> the chess engine has a .quit() function that terminates it, I connected the QThread's 'finished' signal to the slot where .quit() is called on the engine process, but still the same error message at app exit
[09:22:46] <altendky> bomex: I told you threads weren't simple. But you also are failing to let us help you.
[09:22:53] <altendky> bomex: and we said that probably wouldn't help
[09:23:11] <altendky> 09:11 <altendky> bpaste.net/+pytb+python
[09:23:37] <altendky> bomex: make the suggested change, share the full code and output
[09:25:12] <bomex> altendky: https://bpa.st
[09:36:55] <altendky> bomex: so there's no error now?
[10:22:06] <bomex> altendky: I have posted what the error message is
[10:23:09] <bomex> altendky: the error message is displayed as a -6
[10:23:37] -!- honigkuchen has quit [Ping timeout: 264 seconds]
[10:24:13] <bomex> I don't know what the -6 number means, but it's not 0 (meaning 'success'), so there's an issue at application exit
[10:45:29] -!- bomex has quit [Remote host closed the connection]
[10:49:49] -!- honigkuchen has joined #pyqt
[11:11:45] <ali1234> TypeError: unable to convert a C++ 'QQmlListProperty<QQuickRectangle>' instance to a Python object
[11:11:48] <ali1234> :(
[11:52:40] -!- cottoneyejim has joined #pyqt
[12:16:54] -!- cottoneyejim has quit [Quit: cottoneyejim]
[12:43:15] <gadesantares> Sorry for not answering before... went out for a while.
[12:43:15] <gadesantares> altendky: I can see a little "glimpse" of a dialog in te middle of the screen but unable to see (it closes inmediatly)
[12:43:15] <gadesantares> The-Compiler: I did dbg with my little knowledge of it and (even with catch catch PyErr_Format) and the results are in https://controlc.com
[12:44:22] <altendky> gadesantares: first thing i thought of was a pyqtproperty that's an int but you have seeded with None?
[12:46:57] <The-Compiler> gadesantares: do "bt" instead of "quit" after the abort ;)
[12:56:57] <altendky> gadesantares: fyi, bpaste.net doesn't have ads (let alone an ad blocker blocker) :]
[13:01:02] <gadesantares> altendky: I was thinkking about that, check the source of one of the widgets https://controlc.com
[13:01:03] <gadesantares> The-Compiler: Here you have https://controlc.com
[13:02:09] <altendky> gadesantares: bpaste.net/+pytb+python for output and code perhaps
[13:02:50] <gadesantares> Sorry I'll switch to bpaste next... just annoyed this time pastebin is banned by firefox for security reasons (?) and I got the first alternative i picked up. I
[13:03:04] <altendky> gist.github.com is good if you have an account
[13:03:05] <The-Compiler> gadesantares: from the stacktrace and code I'm guessing this is to blame somehow: defaultIndex = QtCore.pyqtProperty(int,getDefaultIndex, setDefaultIndex)
[13:03:21] * altendky glances knowingly at the property
[13:04:37] <The-Compiler> gadesantares: maybe make sure setDefaultIndex is never called with None? I also can't see where (if at all) you're initializing self._defaultIndex (except via setDefaultIndex, though that might be fine)
[13:05:47] <gadesantares> The funny thing is that , in fact, defaultIndex is in init() and is the only variable which doesn't default to None but to an integer (1)
[13:06:43] <gadesantares> But I guess I have to check that out. Maybe also setting strings to '' instedd to None might help, however, I should rewrite the thing a little
[13:06:52] <altendky> gadesantares: side note, no need to pass parameters to super() (unless you are running in py2 but...)
[13:07:37] <altendky> and some reason not to use the decorator form of pyqtProperty? (you can use it like @property right?)
[13:08:36] <altendky> this seems vaguely familiar but it would have been several years ago that i setup this part of my code.
[13:09:05] <altendky> i feel like there were what seemed like some unnecessary accesses to properties, or something...
[13:09:44] <altendky> but in general i am used to seeding the backing attribute in __init__ rather than calling the setter.
[13:12:41] <altendky> gadesantares: also except: pass is kinda bound to waste a pile of time. when you connect you get a thing returned that you can use to disconnect. or at least catch just the exception you expect. likewise for printing, that's minimally better than pass
[13:13:38] <altendky> i have a sys.excepthook that pops up a dialog for uncaught exceptions. much simpler than adding prints all over and more complete output info too.
[13:43:07] <gadesantares> altendky: that's beyond my current knowledge of Python. In fact your directions will need several months to be completely understood (particularly decorators) but I'll give a try.
[13:43:07] <gadesantares> Also I've done some poorman's ninja debug techniques with a thrilling result: Because I wanted to test all you said, I just reinstalled my module (there are many subclassed widgets like the customcombodb) to discover that... in fact customcombodb works!!! So it means that the offending lines should be among the other 13 widgets. Well, at least they are not 123. Right now, can't figure out how to test it but I'm
[13:43:07] <gadesantares> checking all the sources
[13:44:46] <gadesantares> I mean, I reinstalled the module with just customcombodb
[13:44:50] <gadesantares> sorry
[13:45:33] <altendky> gadesantares: for the decorator form, see the example at the end of https://www.riverbankcomputing.com
[13:46:00] <altendky> you decorate the reader method with pyqtProperty and then you decorate the setter with <the reader name>.setter
[13:46:39] <altendky> gadesantares: if you install with --editable then you can just delete files one by one without reinstalling
[14:06:35] <gadesantares> Yes, I just tested the example (and realized that then in __init__ i just have to say self.defaultIndex=whatever (very cool!) and I think I'll adopt it from now on.
[14:10:04] <gadesantares> And after your very appreciated lessons, I've found the culprit: In one of the widgets I defaulted an int to None. When a boolean or a string is defaulted to None, there is no problem ( I gues as a string None will be converted to '' or 'None' and boolean might default to False, but C++ doesn't know which value to set so it complaints)
[14:11:15] <gadesantares> Just altendky The_Compiler Ali1234 thank you very much for your help and lessons. I learnt a lot today!!!
[14:11:48] -!- sazawal has joined #pyqt
[14:11:53] <gadesantares> Now it's time to recode with decorators etc.
[14:11:59] <altendky> gadesantares: bool(None) works
[14:12:03] <altendky> so does str(None)
[14:12:06] <altendky> int(None) doesn't :]
[14:12:45] <altendky> and i would consider setting the backing attribute in init rather than just calling the setter effectively
[14:14:01] <ali1234> i wish the font stretch property was exposed in QML
[14:14:17] <ali1234> i could immediately delete like 50 loc if it was
[14:18:39] -!- sazawal has quit [Read error: Connection reset by peer]
[14:18:59] -!- sazawal has joined #pyqt
[14:19:31] -!- sazawal has quit [Max SendQ exceeded]
[14:21:01] <gadesantares> altendky: yes, in(None) doesn't work and the others do work. It makes sense, at the end None could be trasnlated for an empty string and for False, but for int it should be arbitrary: 0, -1, 100?
[14:21:01] <gadesantares> When you say _setting the backing attribute in init_ you mean say self.defaultIndex=whatever in init rather than self.setDefaultIndex(whatever), isn't it? In that case, I already tested and will switch to it for sure
[14:21:25] <gadesantares> it seems to be easier to read for me
[14:22:31] <altendky> if your setter is `def setIt(self, value): self._it = value` then `self._it` is the 'backing value' as i am referring to it
[14:22:51] <altendky> bypassing the property and just setting the value directly
[14:23:05] <altendky> i'm not _sure_ it is better and i won't be forming a good argument. it just feels proper to me.
[14:23:49] <altendky> a property doesn't hold a value, it manages access to a value
[14:25:20] <ali1234> how do i rewrite this in python: viewer.rootObject()->findChild<QObject*>("text1")
[14:25:33] <ali1234> from https://stackoverflow.com
[14:25:49] <altendky> viewer.rootObject().findChild(QObject, 'text1') or so
[14:25:59] <altendky> help(the_pyqt_thing) can help sometimes
[14:26:02] <ali1234> hmm. i tried that and it did not work (it returned none)
[14:26:09] <altendky> mm...
[14:26:16] <gadesantares> altendky aaah Ok, I see your point. Thanks!!!
[14:29:51] <ali1234> huh, findCHild searches for objectName, not id
[14:30:33] <ali1234> ah, because you can use it to find multiple children
[14:30:38] <ali1234> that's actually kind of handy
[14:30:53] <altendky> ali1234: are you doing this to pull widgets out of a thing made from a .ui?
[14:31:35] <ali1234> replace .ui with .qml and yes
[14:32:00] <altendky> mm, not sure how qml works in this regard but i definitely don't search with .ui stuff
[14:32:25] <ali1234> i'm dynamically generating cells with a Repeater
[14:32:33] <ali1234> it's kind of horrific
[14:32:44] <ali1234> but it works
[14:38:24] <ali1234> apparently objects created by a repeater don't inherit objectName from the template
[14:38:33] <ali1234> because it doesn't work
[15:10:31] -!- michyamrane has joined #pyqt
[15:11:51] -!- _AleX_ has joined #pyqt
[15:12:56] <michyamrane> hello
[15:27:55] -!- michyamrane has quit [Ping timeout: 246 seconds]
[16:48:22] -!- jmarsac_ has joined #pyqt
[16:50:51] -!- jmarsac has quit [Ping timeout: 272 seconds]
[17:02:32] -!- SpinTronix has quit [Quit: Konversation terminated!]
[17:08:24] -!- oprypin has quit [Quit: Bye]
[17:08:33] -!- oprypin has joined #pyqt
[17:08:51] -!- oprypin has quit [Client Quit]
[17:08:59] -!- oprypin has joined #pyqt
[17:23:04] -!- yustin_42 has quit [Ping timeout: 256 seconds]
[17:24:11] -!- frispete_ has quit [Ping timeout: 260 seconds]
[17:24:25] -!- frispete_ has joined #pyqt
[17:57:58] -!- BPL has quit [Quit: Leaving]
[18:32:14] -!- jmarsac_ has quit [Read error: Connection reset by peer]
[19:39:14] -!- ali1234 has quit [Remote host closed the connection]
[22:54:57] -!- LionOpeter has joined #pyqt