IPython笔记本:使用GUI(Qt对话框)打开/选择文件



当您在笔记本中对不同的数据文件执行相同的分析时,以图形方式选择数据文件可能很方便。

在我的 python 脚本中,我通常实现一个 QT 对话框,该对话框返回所选文件的文件名:

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]

但是,从笔记本运行此函数

full_fname = gui_fname()

导致内核死亡(并重新启动):

有趣的是,将这 3 个命令放在 3 个单独的单元格中有效

%matplotlib qt
full_fname = gui_fname()
%matplotlib inline

但是当我将这些命令放在一个单元格中时,内核又死了。

这可以防止创建像gui_fname_ipynb()这样的函数,该函数透明地允许选择具有GUI的文件。

为了方便起见,我创建了一个笔记本来说明这个问题:

  • 使用 GUI 打开/选择文件(Qt 对话框)

关于如何从 IPython 笔记本中执行文件选择对话框的任何建议?

在Windows上使用Anaconda 5.0.0(Python 3.6.2,IPython 6.1.0),以下两个选项都对我有用。

选项 1:完全在 Jupyter 笔记本中:

单元格 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]

单元格 2:

gui_fname()

这对我有用,但似乎有点...脆弱。如果我将这两件事合并到同一个单元格中,它会崩溃。或者如果我省略%gui qt,它会崩溃。如果我"重新启动内核并运行所有单元格",它不起作用。所以我有点喜欢这个其他选择...

更可靠的选项:在新进程中打开对话框的单独脚本

(基于此处的 mkrog 代码。

将以下内容放在一个名为 blah.py 的单独 PYTHON 脚本中:

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])

。在你的 JUPYTER 笔记本中

import blah
blah.gui_fname()

我有一个通用代码,它可以毫无问题地完成工作。这是我的建议:

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)

希望它有用

这种行为是IPython中的一个错误:

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

这是在这里修复的:

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

打开 gui 对话框的功能应该适用于当前主版和即将发布的 2.0 版本。

到目前为止,最后一个 1.x 版本 (1.2.1) 不包括修复程序的向后移植。

编辑:示例代码仍然崩溃IPython 2.x,请参阅此问题。

最新更新