TabViewer / gtabview

Simple graphical tabular data viewer
MIT License
33 stars 3 forks source link

Jupyter notebook support #32

Closed matthewgson closed 3 years ago

matthewgson commented 4 years ago

When I try to view pandas dataframe using gtabview with jupyter notebook, it prints out like <gtabview.ViewController at 0x1c3427715c8> and output pops up, but then it freezes.

Is there a possible solution to use gtabview within jupyter notebook?

wavexx commented 4 years ago

See the README about correct initialization for notebooks (you have to set DETACH before calling view).

Sadly I just tried on a current version of jupyter/pyqt5 and I cannot it to work (not sure yet what exactly changed in either jupyter or pyqt5).

axil commented 3 years ago

I confirm this behaviour but with relatively large datasets only: 300x300 works fine, but 4200x12 doesn't. Both in normal mode from jupyter notebook. When opening the datasets from commandline both get displayed perfectly well.

In DETACH=True mode I get the following error:

Exception in thread Thread-6:
Traceback (most recent call last):
  File "c:\python37-64\lib\threading.py", line 926, in _bootstrap_inner
    self.run()
  File "c:\python37-64\lib\site-packages\gtabview\__init__.py", line 64, in run
    APP = QtGui.QApplication.instance()
AttributeError: module 'PyQt5.QtGui' has no attribute 'QApplication'
wavexx commented 3 years ago

The above error should be fixed in master, along with a fix for python 3.9. I think it's time for a new release soon...

wavexx commented 3 years ago

I've been retesting this with jupyter, but it looks like something is preventing Qt to work at all inside a notebook.

When running in detached mode, the windows shows up, but doesn't seem to receive any event. A stack trace seems to reveal that python is stuck inside a selector loop and doesn't relinquish control until some asyncio event occurs.

In normal mode Qt is not even receiving events despite running a blocking event loop.

Incredibly annoying to debug due to the sheer size of both environments. I'm pushing this to the next release..

wavexx commented 3 years ago

Looks like PyQt5 cannot be started from a separated thread like in earlier versions, which kinds of defeat the purpose of the "DETACH" flag. So we need assistance from the main program's loop to get the same.

I managed to get it working on jupyter by hooking up on the main asyncio's event loop, with polling... At least on X11 this can be made optimal through the QtX11Extras module, fetching the xcb connection descriptor, and waiting on the descriptor itself instead of waiting.

When using Matplotlib with the Qt backend it already handles the event loop for us, so we just rely on matplotlib itself for event dispatching.

On windows/mac I assume the polling approach will work, but I have no idea how this could be turned optimal

wavexx commented 3 years ago

After further testing, it seems that Qt5 is also reading from the X socket with a separate thread, so the option of monitoring the socket is also busted, since events get skipped if the thread reads them before we finish...

wavexx commented 3 years ago

I managed to test the fix in ipython and jupyter with both inline and separate plot windows on linux. If somebody could test this under windows it would be great!