#pyqt | Logs for 2018-09-10
Back
[00:48:08] -!- delipickle has joined #pyqt
[00:58:06] -!- delipickle has quit [Quit: Leaving]
[01:32:38] -!- kdas_ has joined #pyqt
[01:33:27] -!- kushal has quit [Ping timeout: 256 seconds]
[02:14:57] -!- anqxyr has joined #pyqt
[02:51:33] -!- anqxyr has quit [Ping timeout: 252 seconds]
[04:48:19] -!- kallesbar has joined #pyqt
[05:48:31] -!- davor has joined #pyqt
[05:48:38] -!- davor has parted #pyqt
[05:54:12] -!- Flaghacker has joined #pyqt
[05:54:35] <Flaghacker> Is there a way to separate stdout and stderr from different QThreads?
[05:56:01] <Flaghacker> For basic python it's easy enough, just change sys.stdout. Unfortunately it looks like that's global.
[06:19:52] -!- mintograde has joined #pyqt
[07:13:00] -!- mintograde has quit [Ping timeout: 252 seconds]
[07:40:32] -!- jthornton has quit [Remote host closed the connection]
[07:42:39] -!- jthornton has joined #pyqt
[08:22:34] -!- frispete_ has joined #pyqt
[08:25:03] -!- frispete has quit [Ping timeout: 245 seconds]
[08:27:52] <altendky> Flaghacker: I forget, why do you have threads?
[08:28:27] <Flaghacker> altendky, An expensive computation runs on a separate thread.
[08:29:16] <altendky> Flaghacker: keep in mind that you won't get extra CPU time for python code.
[08:29:39] <Flaghacker> Thqt's fine, it just can't block the GUI.
[08:29:58] <altendky> Flaghacker: I have something like that and haven't been pleased with the performance. I've considered dropping the thread and adding processEvents calls instead
[08:30:46] <Flaghacker> The actual code spawns a bunch of multiprocess stuff so the extra perforance comes from that, the main thread still has to do so;e heavy computations though.
[08:30:59] <altendky> Flaghacker: i suppose you could pass it another file to write to and use that in any print statements (or just the_file.write() instead)
[08:31:15] <Flaghacker> processEvents wouldn't work because the code isn't QT-specific.
[08:31:54] <altendky> Flaghacker: you could still pass it a 'yield' function to call
[08:32:08] <Flaghacker> And passing a file/logger would be a great solution but it's a couple thousand lines of legacy code written by non-programmers :/
[08:32:19] <altendky> Flaghacker: but why not put it in a separate process itself?
[08:33:03] <Flaghacker> Because I need intermediate returmn values, and multiprocessing doesn't seem to allow that, callbacks don't work.
[08:33:06] <altendky> Flaghacker: alrighty. I don't know if a way but all in #python. Though, a couple thousand lines isn't much to go through and add file=x to
[08:33:57] <altendky> Flaghacker: the actual multiprocessing module? It's mostly discouraged, though I can't provide a 'drop-in' replacement library
[08:35:41] <Flaghacker> I would just go trough it but they keep writing new stuff including print() calls into it, I would love to give them a little bubble. I'll probably just have to push trough :(
[08:36:10] <Flaghacker> I also looked at concurrent.futures but that didn't allow it either.
[08:38:40] <altendky> Flaghacker: tell them to use a new interface you provide
[08:38:57] <Flaghacker> altendky, yeah I'll do that
[08:39:08] <altendky> Flaghacker: i don't think it's a great choice but you could also override print for that file :|
[08:39:19] <Flaghacker> altendky, I was hoping for a quick fix but oh well
[08:39:21] <altendky> just shadow the builtin
[08:39:38] <Flaghacker> Hmm that is tempting.
[08:39:42] <altendky> Flaghacker: explicit is good... and often a bit more wrok on the front end
[08:41:17] <altendky> Flaghacker: but i'd still consider passing a 'yield' callable (passing in processEvents) and dropping the thread. though it kind of depends on what your blocking calls actually are. or, multiprocessing allows shared objects. i presume they have a queue or such you could shove results back through.
[08:41:49] <Flaghacker> The blocking calls are numpy and other library stuff, so very little can be done there.
[08:42:11] <Flaghacker> The thread works fine for now.
[08:42:32] <altendky> Flaghacker: but it still depends if individual ones take a long time. also, numpy might be releasing the gil so you might be getting some extra cpu time.
[08:45:15] <Flaghacker> Hmm? If numpy releases the GIL the thread would be better, right?
[08:45:58] <altendky> Flaghacker: it would have another upside, yeah. are you actually using any of the qthread features?
[08:46:41] <Flaghacker> I have pyqtsignals for the intermediate returns values, so i guess I'm using some QObject features?
[08:48:25] <altendky> Flaghacker: QObject yes, QThread no. QThread provides an event loop which is needed to receive signals but not to send.
[08:48:38] <altendky> Flaghacker: but, it sounds like this is a non-cancellable operation
[08:49:49] <Flaghacker> So I could get away with a QObject and a normal Thread?
[08:49:54] <Flaghacker> And no it's non-cancelable.
[08:50:36] <altendky> Flaghacker: yes. (just to say it, in either case, don't inherit from the thread class...)
[08:51:24] <Flaghacker> :O oops
[08:51:54] <Flaghacker> I can't inherit from QThread and override run?
[08:52:07] <altendky> Flaghacker: generally when people inherit from QThread they don't actually start the event loop anyways so they lose the main feature of a QThread over a Python thread
[08:53:23] <altendky> Flaghacker: consider the first example. http://doc.qt.io not saying it's a great design but it covers the worker object and a standard QThread
[08:53:51] <altendky> Flaghacker: since run is where the thread starts the event loop, overriding it and presumably not calling the event loop... kind of defeats the purpose of a QThread.
[08:54:16] <altendky> Flaghacker: you could still move objects to the thread but that's kind of, well, might be mostly irrelevant without an event loop in the thread
[08:54:27] <Flaghacker> I see.
[08:55:01] <altendky> Flaghacker: in python instead of inheriting and overriding there's literally a target parameter to the thread constructor. just write a function and pass it
[08:55:59] -!- JanC has quit [Remote host closed the connection]
[08:56:14] -!- JanC has joined #pyqt
[08:58:27] <altendky> Flaghacker: i got tired of inheriting from QObject just to be able to have signals so i made a little thing to allow pyqtSignal's effectively on non-QObjects. some feel it's too magical, so be warned. Basically, it creates a QObject to host the signal behind the scenes. i did this after realizing i had been overriding QObject methods for a couple years without realizing it.
[08:59:49] <Flaghacker> Ah that's cool, I've had to do some inconvenient stuff a couple of times too (before I knew about QObject even)
[08:59:55] <Flaghacker> Could you link the code?
[09:00:51] <altendky> Flaghacker: https://github.com i've meant to more closely tie that last line outside the class to it... but for now you just have to not forget it.
[09:01:13] <altendky> Flaghacker: for normal uses it's a drop in replacement for pyqtSignal
[09:01:41] <altendky> `class X: the_signal = Signal(int, str)` and `self.the_signal.connect(lambda: print('blue')` etc
[09:02:15] <Flaghacker> Coo, thanks!
[09:02:23] <Flaghacker> What's the attribute_name thingy?
[09:03:52] <altendky> Flaghacker: the Signal stores information in an attribute of your class instances. to avoid collisions i decided to use the full path like epyqlib.utils.qt.Signal in the name. as such it has to be assigned after the class is created. though, iirc, i want to switch it to a decorator instead to more closely tie it to the class definition.
[09:04:14] -!- Siecje has joined #pyqt
[09:04:22] <altendky> Flaghacker: you could either copy the identifier_path() function as well, or just set attribute_name to whatever is unique enough for your case.
[09:04:52] <altendky> hmm... i would have thought i'd prefix it with __ but oh well...
[09:05:07] <altendky> anyways, with .'s in it you won't accidentally type it in code :]
[09:05:19] <Flaghacker> Ah and you didn't put it in the class itself because the class needs to actually load first!
[09:06:57] <altendky> yup
[09:07:15] <altendky> Flaghacker: i explored a few options but none were totally satisfactory and i didn't get around to applying any of them. https://repl.it
[09:09:20] <Flaghacker> I still have to learn what decorators are and how they work sometime.
[09:09:45] <altendky> Flaghacker: `@d; def f():...` -> `def f():...; f = d(f)`
[09:09:47] <altendky> that's it :]
[09:10:16] <Flaghacker> Ah that's not too bad.
[09:10:43] <altendky> Flaghacker: the def or class that follows the decorator gets passed to it as a parameter. the decorator then returns a thing. sometimes the decorator modifies before returning, sometimes it builds a replacement to return, sometimes it just collects the thing such as into a list.
[09:11:06] <altendky> Flaghacker: lots of different patterns, but it all comes back to just a thing getting passed and a thing getting returned
[09:13:23] <Flaghacker> Damm properties are very cool then. Use the results of the previous decorator as the decorator of the next one1
[09:13:45] <altendky> Flaghacker: yeppers
[09:14:49] <altendky> Flaghacker: in the first decorator you replaced the method with a descriptor (my Signal class is also a descriptor) and then use the pattern in the following decorations to collect the other methods onto that descriptor
[09:15:26] <altendky> Flaghacker: in short, descriptors let you put code in the middle of the attribute access so you can do and return whatever you want.
[09:16:26] <altendky> Flaghacker: doing `self.the_signal` triggers the `__get__()` method of `Signal` so it can go get the proper `pyqtBoundSignal` off another object and return it to you.
[09:17:11] <Flaghacker> Lua metatable memories are coming back here :)
[09:17:25] <altendky> Flaghacker: never really did any Lua, but perhaps
[11:14:49] -!- Flaghacker has quit [Quit: Leaving]
[13:26:21] -!- anqxyr has joined #pyqt
[14:53:34] -!- Afrix has joined #pyqt
[16:01:37] -!- nitro25 has quit [Quit: He gone...]
[16:24:12] -!- Afrix has quit [Read error: Connection reset by peer]
[16:24:29] -!- mintograde has joined #pyqt
[17:06:07] -!- Siecje has quit [Quit: Leaving.]
[17:27:15] -!- anqxyr has quit [Read error: Connection reset by peer]
[17:35:36] -!- kallesbar has quit [Ping timeout: 252 seconds]
[19:36:43] -!- kdas_ has quit [Remote host closed the connection]
[19:37:02] -!- kushal has joined #pyqt
[22:11:44] -!- necrose99 has joined #pyqt
[22:25:25] -!- mintograde has quit [Ping timeout: 246 seconds]
[22:30:55] -!- stochastix has joined #pyqt