IPython Notebook: Open/select file with GUI (Qt Dialog)
Asked Answered
B

3

18

When you perform the same analysis in a notebook on different data files, may be handy to graphically select a data file.

In my python scripts I usually implement a QT dialog that returns the file-name of the selected file:

from PySide import QtCore, QtGui

def gui_fname(dir=None):
    """Select a file via a dialog and return the file name.
    """
    if dir is None: dir ='./'
    fname = QtGui.QFileDialog.getOpenFileName(None, "Select data file...", 
            dir, filter="All files (*);; SM Files (*.sm)")
    return fname[0]

However, running this function from an notebook

full_fname = gui_fname()

causes the kernel to die (and restart):

Interestingly, puttying this 3 command in 3 separate cells works

%matplotlib qt
full_fname = gui_fname()
%matplotlib inline

but when I put those commands in one single cell the kernel dies again.

This prevents to create a function like gui_fname_ipynb() that transparently allows selecting a file with a GUI.

For convenience, I created a notebook illustrating the problem:

Any suggestion on how to execute a dialog for file selection from within an IPython Notebook?

Berthaberthe answered 26/12, 2013 at 20:36 Comment(0)
G
15

Using Anaconda 5.0.0 on windows (Python 3.6.2, IPython 6.1.0), the following two options are both working for me.

OPTION 1: Entirely in a Jupyter notebook:

CELL 1:

%gui qt

from PyQt5.QtWidgets import QFileDialog

def gui_fname(dir=None):
    """Select a file via a dialog and return the file name."""
    if dir is None: dir ='./'
    fname = QFileDialog.getOpenFileName(None, "Select data file...", 
                dir, filter="All files (*);; SM Files (*.sm)")
    return fname[0]

CELL 2:

gui_fname()

This is working for me but it seems a bit...fragile. If I combine these two things into the same cell, it crashes. Or if I omit the %gui qt, it crashes. If I "restart kernel and run all cells", it doesn't work. So I kinda like this other option...

MORE RELIABLE OPTION: Separate script that opens dialog box in a new process

(Based on mkrog code here.)

PUT THE FOLLOWING IN A SEPARATE PYTHON SCRIPT CALLED blah.py:

from sys import executable, argv
from subprocess import check_output
from PyQt5.QtWidgets import QFileDialog, QApplication

def gui_fname(directory='./'):
    """Open a file dialog, starting in the given directory, and return
    the chosen filename"""
    # run this exact file in a separate process, and grab the result
    file = check_output([executable, __file__, directory])
    return file.strip()

if __name__ == "__main__":
    directory = argv[1]
    app = QApplication([directory])
    fname = QFileDialog.getOpenFileName(None, "Select a file...", 
            directory, filter="All files (*)")
    print(fname[0])

...AND IN YOUR JUPYTER NOTEBOOK

import blah
blah.gui_fname()
Geehan answered 18/10, 2017 at 15:50 Comment(1)
This worked for me on Windows 10 with Jupyter (Classic) Notebook v6.1.5, but it is kind of clunky, since I want the notebook to be self-contained. So I use a iPython Notebook magic command "%%writefile <<< code above>>>" to write out the Python input cell source code above to a local file, and then import the module and run it in the next cell. The Qt File Chooser opens as a "pop-behind" rather than a pop-up dialog, which is a bit of a hassle. However, it works. Thank you.Fritzfritze
P
4

I have a universal code where it does its job without any problem. Here is my sugestion:

try:
    from tkinter import Tk
    from tkFileDialog import askopenfilenames
except:
    from tkinter import Tk
    from tkinter import filedialog

Tk().withdraw() # we don't want a full GUI, so keep the root window from appearing
filenames = filedialog.askopenfilenames() # show an "Open" dialog box and return the path to the selected file

print (filenames)

hope it can be useful

Pleasantry answered 24/9, 2019 at 23:50 Comment(2)
Is it correct that all of these solutions only work if the jupyter lab instance is running on the same host as the browser?Flexible
This does not work with Jupyter Classic Notebook v6.1.5 or Spyder v4.2.3. It hangs the iPythonNB kernel and requires restarting the server kernel. I tried using it in Spyder, and it opens the Tkinter dialog, but only as a "pop-behind", and then after selecting a file, the filenames are never actually returned to the calling program. This gets my downvote in 2021.Fritzfritze
B
2

This behaviour was a bug in IPython:

https://github.com/ipython/ipython/issues/4997

that was fixed here:

https://github.com/ipython/ipython/pull/5077

The function to open a gui dialog should work on current master and on the oncoming 2.0 release.

To date, the last 1.x version (1.2.1) does not include a backport of the fix.

EDIT: The example code still crashes IPython 2.x, see this issue.

Berthaberthe answered 16/3, 2014 at 5:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.