IPython Notebook: открыть/выбрать файл с графическим интерфейсом (Qt Dialog)
Когда вы выполняете тот же анализ в ноутбуке в разных файлах данных, может быть удобно графически выбирать файл данных.
В моих сценариях 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()
, которая прозрачно позволяет выбрать файл с графическим интерфейсом.
Для удобства я создал блокнот, иллюстрирующий проблему:
Любое предложение о том, как выполнить диалог выбора файлов из IPython Notebook?
Ответы
Ответ 1
Используя Anaconda 5.0.0 в Windows (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]
CELL 2:
gui_fname()
Это работает для меня, но кажется немного... хрупким. Если я объединю эти две вещи в одну и ту же камеру, она рухнет. Или, если я опущу %gui qt
, он падает. Если я "перезапустить ядро и запустить все ячейки", это не работает. Так что мне нравится этот другой вариант...
БОЛЬШЕ НАДЕЖНОГО ВАРИАНТА: отдельный скрипт, открывающий диалоговое окно в новом процессе
(На основе кода mkrog здесь.)
ПОСТАВИТЬ СЛЕДУЮЩИЙ В ОТДЕЛЬНОМ ПИФОНЕ СЦЕНАРИЙ 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])
... И В ВАШЕЙ ЗАПИСИ JUPYTER
import blah
blah.gui_fname()
Ответ 2
Это поведение было ошибкой в IPython:
https://github.com/ipython/ipython/issues/4997
который был исправлен здесь:
https://github.com/ipython/ipython/pull/5077
Функция открытия диалога gui должна работать с текущим мастером и в выпуске oncoming 2.0.
На сегодняшний день последняя версия 1.x(1.2.1) не включает резерв исправления.
РЕДАКТИРОВАТЬ: Код примера по-прежнему вызывает сбой IPython 2.x, см. эту проблему.
Ответ 3
У меня есть универсальный код, где он делает свою работу без проблем. Вот мое предположение:
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)
надеюсь, что это может быть полезно