Using the main terminal : impossible since that it is blocked by the
QApplication (by app.exec_())
You can omit app.exec()
if you are within a Python terminal and it will not be blocking. As explained here this works because...
PyQt5 installs an input hook (using PyOS_InputHook) that processes
events when an interactive interpreter is waiting for user input. This
means that you can, for example, create widgets from the Python shell
prompt, interact with them, and still being able to enter other Python
commands.
For example, enter the following in the Python shell to have a working Qt widget and a non-blocking REPL simultaniously.
$> python
Python 3.7.6 | packaged by conda-forge | (default, Jan 7 2020, 22:05:27)
[Clang 9.0.1 ] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from PyQt5.QtWidgets import QApplication, QWidget
>>> a = QApplication([])
>>> w = QWidget()
>>> w.show()
>>> w.raise_()
IPython has similar functionality. If you start it with ipython --gui=qt
, or type %gui qt
in the terminal you get the same effect...
$> ipython
Python 3.7.6 | packaged by conda-forge | (default, Jan 7 2020, 22:05:27)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.11.1 -- An enhanced Interactive Python. Type '?' for help.
In [1]: %gui qt
In [2]: from PyQt5 import QtWidgets
In [3]: win = QtWidgets.QPushButton("click me")
In [4]: win.show()
In [5]: win.raise_()
I recommend to use IPython because it's better suited for interactive work and it will work with PySide (perhaps regular Python and PySide will also work; I didn't check).
See also my earlier answer here
Finally, even though this works I don't know how good the performance is. It's a good solution for a hobby project but if you have many users I would consider to implement an 'in-app' terminal or some form of inter-process communication.