(If someone has a high-quality way to use asyncio or Twisted with the Qt event loop, I'd probably bump Python a bit higher.)
(If someone has a high-quality way to use asyncio or Twisted with the Qt event loop, I'd probably bump Python a bit higher.)
But what makes those apps resource hungry and sluggish is usually not the UI: it's the whole lot of applicationg logic that's buried into their cores using Javascript code for stuff the language was not designed for.
I'm primarly a Python developer too, and on that respect I like Python's approach to C extensions. It's easy enough to rewrite your application logic into C when performance is important, and in general I think experienced Python programmers will do just that. The problem with Electron is both the lack of support for doing this, and the lack of experienced developers willing to do it.
I am reasonably excited about WebAssembly as a solution for this for web apps. (Although web apps also have a natural front-end/back-end separation, and people consider JS as just one of many potential options for a back-end language, which helps a lot here.) It does surprise me that there isn't good support for doing this with actual native code on Electron.
Priority #1: Runtime, your code will (hopefully) be run a lot more than it does anything else.
Priority #2: Debug, your code will be debugged more than it is read
Priority #3: Reading, you will probably read your code a significant amount more than you write code.
Priority #4: Writing. A software should spend the least amount of time on a CPU being written.
I'm not saying that you should only focus on making fast/slick runtimes that are easily debuggable above literally everything else; but you should absolutely have slanted priorities towards this goal.
And in that respect, why wouldn't you learn the right tool for the job?
Given that, what makes sense to optimize for? The slowest, most error-prone processor in the mix is, the wetware in your head.
So, almost all of the time, put #1 at the bottom of the list. Put #3 next, because once it works, the slowest process is relearning why it works, necessary to debug or extend it.
#2 and #4 are simultaneous.
So, for most coding most of the time on most projects, write dead-obvious code using normal design patterns and simplest abstractions. Because time is money, and your wetware time is millions of times more expensive than cpu time.
Just because your code isn't in a tight loop doesn't mean you shouldn't think about performance. If you waste CPU resources then the rest of the system that is in a tight loop will have more switches to do. If you waste memory then the code in the tight loop will have memory evicted from it's precious memory cache. Just because your process is not CPU bound does not mean you aren't having an impact on overall system performance.
If you're running your own servers do whatever you want, but if you're making consumer software then don't pretend you're software is the only thing running.
We should write code that's idiomatic and clear if we want easy debugging.
Your other point about "wetware is more expensive" is a statement about how much you're scaling. Another 100ms on facebooks home page load is an aggregate of at least a dozen hours a day taken from users, so if it costs a developer a dozen hours to remove that performance hit then it's absolutely worth it.
Performance should be the default, not the edge case.
My argument is about runtime, not about developer comfort - if you have race conditions between threads, or deadlocks, or blocking I/O on the UI thread, that's a runtime problem, not a developer comfort problem.
(I do also disagree with your priorities, in part because if you get #4 right you avoid a lot of #2, but I wanted to be clear about what my argument is.)
I've experimented around with Quamash[1] a bit with Asyncio and it seems to work nicely! Looking at CI it seems to have some rough edges (at least on Windows) though.
It looks like this is done by subclassing QAbstractEventDispatcher and filling out virtual functions registerSocketNotifier(), registerTimer(), etc. I suppose you could do this for asyncio/Twisted, but I'd prefer to import something where someone has done this for me and is accepting bug reports from the community, because this is the sort of thing that's made of edge cases that are hard to notice in testing.