Быстрый и простой диалог файла в Python?

105

У меня есть простой скрипт, который анализирует файл и загружает его содержимое в базу данных. Мне не нужен пользовательский интерфейс, но прямо сейчас я предлагаю пользователю проанализировать файл, raw_inputчто наиболее неприятно, особенно потому, что пользователь не может скопировать / вставить путь. Мне нужен быстрый и простой способ представить диалоговое окно выбора файла пользователю, он может выбрать файл, а затем он будет загружен в базу данных. (В моем случае, если бы они случайно выбрали неправильный файл, он не смог бы выполнить синтаксический анализ и не стал бы проблемой, даже если бы он был загружен в базу данных.)

import tkFileDialog
file_path_string = tkFileDialog.askopenfilename()

Этот код близок к тому, что я хочу, но он оставляет открытым раздражающий пустой фрейм (который не может быть закрыт, вероятно, потому, что я не зарегистрировал обработчик события закрытия).

Мне не нужно использовать tkInter, но, поскольку он входит в стандартную библиотеку Python, он является хорошим кандидатом для самого быстрого и простого решения.

Какой быстрый и простой способ запросить файл или имя файла в сценарии без какого-либо другого пользовательского интерфейса?

Кнопки840
источник
Незначительное исправление: вы можете вставить в терминал (похоже, что вы работаете в Windows), щелкнув правой кнопкой мыши в текстовой области и выбрав «Вставить» в контекстном меню.
Deestan
1
В приглашении Python raw_input нет контекстного меню.
Buttons840
2
raw_input происходит в терминале, в котором есть меню, вызываемое правой кнопкой мыши.
Deestan

Ответы:

205

Tkinter - самый простой способ, если вы не хотите иметь никаких других зависимостей. Чтобы отобразить только диалог без каких-либо других элементов графического интерфейса, вам нужно скрыть корневое окно, используя withdrawметод:

import tkinter as tk
from tkinter import filedialog

root = tk.Tk()
root.withdraw()

file_path = filedialog.askopenfilename()

Вариант Python 2:

import Tkinter, tkFileDialog

root = Tkinter.Tk()
root.withdraw()

file_path = tkFileDialog.askopenfilename()
томводы
источник
3
Это должен быть принятый ответ. Это просто, эффективно, и пока вы не создаете новые корневые окна Tk снова и снова, это нормально (не говоря уже о том, что это именно тот ответ, который я искал, когда наткнулся на эту ветку).
Эндрю
2
Я просто использовал это в своей работе. Он отлично работает в Fedora, но в Ubuntu портит любые последующие цифры matplotlib. В значительной степени после pylab.show () он зависает. Я все еще могу печатать в терминале, но ничего не происходит. Также для моей программы процессор переходит на 0%. Любой совет?
Diana
17
На python3:tkinter.filedialog.askopenfilename()
jfs
10
На python2: import Tkinter as tkand import tkFileDialogandfile_path = tkFileDialog.askopenfilename()
SaschaH 08
9
Это не работает в MacOS: диалоговое окно открывается, но перестает отвечать, и весь скрипт зависает.
Периодическое техническое обслуживание
26

Вы можете использовать easygui :

import easygui

path = easygui.fileopenbox()

Для установки easyguiможно использовать pip:

pip3 install easygui

Это единственный чистый модуль Python ( easygui.py), который использует tkinter.

jfs
источник
6
Проект easygui закрыт, не обслуживается в дальнейшем - в настоящее время он выдает ошибку / исключение при работе на Python 3.5, возможно, рассмотрите другие варианты
pepe
2
@pepe: я не вижу никаких уведомлений в репозитории проекта (последняя фиксация - 15 мая)
jfs
хорошо знать, ТНХ, возможно , кто - то поднял его: см easygui.wordpress.com/2013/03/06/easygui-project-shuts-down-2
Pepe
@Zanam, очевидно, это работает. Но могут быть ошибки .
jfs
Если у вас есть проблемы с комбинацией tkinter + matplotlib, это может спасти вам день!
Куонг Чыонг Хай,
20

Попробуйте с wxPython :

import wx

def get_path(wildcard):
    app = wx.App(None)
    style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST
    dialog = wx.FileDialog(None, 'Open', wildcard=wildcard, style=style)
    if dialog.ShowModal() == wx.ID_OK:
        path = dialog.GetPath()
    else:
        path = None
    dialog.Destroy()
    return path

print get_path('*.txt')
ТуманПтица
источник
5

Если вам не нужен пользовательский интерфейс или вы ожидаете, что программа будет работать в CLI, вы можете проанализировать путь к файлу как аргумент. Это позволит вам использовать функцию автозаполнения вашего интерфейса командной строки, чтобы быстро найти нужный файл.

Это, вероятно, будет удобно только в том случае, если сценарий не является интерактивным, кроме ввода пути к файлу.

SQDK
источник
Это верное решение, хотя мне становится грустно каждый раз, когда мне приходится использовать командную строку Windows. Я нахожусь в среде Windows.
Buttons840
2
Понимаю. CLI в Windows настолько плох по сравнению с Unix. Я понимаю, почему средство выбора файлов было бы удобным. Я предполагаю, может быть, перетащить файл на скрипт, а затем прочитать имя файла в качестве аргумента? ( mindlesstechnology.wordpress.com/2008/03/29/… ) Это упростило бы задачу, если бы сначала не было физического копирования файла. Я не использую банкомат с Windows, поэтому я не могу проверить, как он себя ведет. Вы можете легко развернуть взлом реестра в файле .reg, если вам нужно установить его на нескольких машинах.
SQDK
В качестве альтернативы вы можете использовать файл .bat, который передает имя файла сценарию в качестве аргумента. Это не требует взлома реестра.
SQDK
3

Используя tkinter (python 2) или Tkinter (python 3), действительно можно отобразить диалог открытия файла (см. Другие ответы здесь). Однако обратите внимание, что пользовательский интерфейс этого диалогового окна устарел и не соответствует новым диалоговым окнам открытия файлов, доступным в Windows 10.

Более того - если вы ищете способ встроить поддержку Python в свое собственное приложение - вы скоро обнаружите, что библиотека tkinter не является открытым исходным кодом и, более того, это коммерческая библиотека.

(Например, поиск по запросу «цены на activetcl» приведет вас на эту веб-страницу: https://reviews.financesonline.com/p/activetcl/ )

Таким образом, библиотека tkinter будет стоить денег для любого приложения, которое хочет встраивать Python.

Мне самому удалось найти библиотеку pythonnet:

(Лицензия MIT)

Используя следующую команду, можно установить pythonnet:

pip3 install pythonnet

А вот рабочий пример использования диалога открытия файла:

https://stackoverflow.com/a/50446803/2338477

Позвольте мне скопировать пример здесь:

import sys
import ctypes
co_initialize = ctypes.windll.ole32.CoInitialize
#   Force STA mode
co_initialize(None)

import clr 

clr.AddReference('System.Windows.Forms')

from System.Windows.Forms import OpenFileDialog

file_dialog = OpenFileDialog()
ret = file_dialog.ShowDialog()
if ret != 1:
    print("Cancelled")
    sys.exit()

print(file_dialog.FileName)

Если вам также не хватает более сложного пользовательского интерфейса - см. Папку Demo в pythonnet git.

Я не уверен насчет переносимости на другие ОС, не пробовал, но .net 5 планируется портировать на несколько ОС (поиск "платформы .net 5", https://devblogs.microsoft.com/dotnet/introduction -net-5 / ) - так что эта технология также является перспективной.

ТармоПикаро
источник
2

pywin32обеспечивает доступ к GetOpenFileNameфункции win32. Из примера

import win32gui, win32con, os

filter='Python Scripts\0*.py;*.pyw;*.pys\0Text files\0*.txt\0'
customfilter='Other file types\0*.*\0'
fname, customfilter, flags=win32gui.GetOpenFileNameW(
    InitialDir=os.environ['temp'],
    Flags=win32con.OFN_ALLOWMULTISELECT|win32con.OFN_EXPLORER,
    File='somefilename', DefExt='py',
    Title='GetOpenFileNameW',
    Filter=filter,
    CustomFilter=customfilter,
    FilterIndex=0)

print 'open file names:', repr(fname)
print 'filter used:', repr(customfilter)
print 'Flags:', flags
for k,v in win32con.__dict__.items():
    if k.startswith('OFN_') and flags & v:
        print '\t'+k
Кевин Смит
источник
Это изменило мой текущий рабочий каталог на каталог, из которого выбираются файлы. Что делать в таком случае?
Mooncrater
@Mooncrater добавить |win32con.OFN_NOCHANGEDIRк Flags, но остерегайтесь предостережение stackoverflow.com/questions/50468051/...
Кевин Смит
Эй, спасибо за предложение. В конечном итоге я возвращался в исходный каталог каждый раз, когда использовал GetOpenFileNameW.
Mooncrater
2

Оцените EasyGUI, очень простой в использовании модуль, который должен работать - http://easygui.sourceforge.net/

Вы должны использовать функцию fileopenbox, подробно описанную на этой странице документации api - https://easygui.readthedocs.io/en/latest/api.html

Timc
источник
1
Извините - на моем телефоне, поэтому я не могу привести пример. Вы хотите использовать fileopenbox - ferg.org/easygui/easygui.html#-fileopenbox
timc
Вторая ссылка не работает.
Thomas Andrews