Szybkie i łatwe okno dialogowe plików w Pythonie?

105

Mam prosty skrypt, który analizuje plik i ładuje jego zawartość do bazy danych. Nie potrzebuję interfejsu użytkownika, ale w tej chwili monituję użytkownika o przeanalizowanie pliku, raw_inputktóry jest najbardziej nieprzyjazny, zwłaszcza, że ​​użytkownik nie może skopiować / wkleić ścieżki. Chciałbym w szybki i łatwy sposób przedstawić użytkownikowi okno dialogowe wyboru pliku, który może wybrać plik, a następnie załadować go do bazy danych. (W moim przypadku, gdyby przypadkowo wybrali niewłaściwy plik, analiza nie powiodłaby się i nie stanowiłoby problemu, nawet gdyby został załadowany do bazy danych).

import tkFileDialog
file_path_string = tkFileDialog.askopenfilename()

Ten kod jest bliski temu, czego chcę, ale pozostawia irytującą pustą ramkę otwartą (której nie można zamknąć, prawdopodobnie dlatego, że nie zarejestrowałem modułu obsługi zdarzeń zamknięcia).

Nie muszę używać tkInter, ale ponieważ znajduje się w standardowej bibliotece Pythona, jest dobrym kandydatem na najszybsze i najłatwiejsze rozwiązanie.

Jaki jest szybki i łatwy sposób na wyświetlenie monitu o plik lub nazwę pliku w skrypcie bez żadnego innego interfejsu użytkownika?

Przyciski840
źródło
Niewielka poprawka: Możesz wkleić do terminala (brzmi to tak, jakbyś był w systemie Windows), klikając prawym przyciskiem myszy w obszarze tekstowym i wybierając „Wklej” z menu kontekstowego.
Deestan
1
W zachęcie Pythona raw_input nie jest dostępne menu prawego przycisku myszy.
Buttons840
2
raw_input dzieje się w terminalu, który ma menu prawego przycisku myszy.
Deestan

Odpowiedzi:

205

Tkinter to najłatwiejszy sposób, jeśli nie chcesz mieć żadnych innych zależności. Aby wyświetlić tylko okno dialogowe bez innych elementów GUI, musisz ukryć okno główne za pomocą withdrawmetody:

import tkinter as tk
from tkinter import filedialog

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

file_path = filedialog.askopenfilename()

Wariant Pythona 2:

import Tkinter, tkFileDialog

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

file_path = tkFileDialog.askopenfilename()
tomvodi
źródło
3
To powinna być akceptowana odpowiedź. To proste, skuteczne i dopóki nie tworzysz w kółko nowych okien głównych Tk, jest w porządku (nie wspominając o tym, że jest to dokładnie odpowiedź, której szukałem, gdy natknąłem się na ten wątek).
Andrew
2
Po prostu użyłem tego również do mojej pracy. Działa dobrze w Fedorze, ale w Ubuntu psuje wszystkie poniższe dane matplotlib. Prawie po pylab.show () zawiesza się. Nadal mogę pisać w terminalu, ale nic się nie dzieje. Również procesor osiąga 0% dla mojego programu. Jakakolwiek rada?
Diana
17
Na pythonie3:tkinter.filedialog.askopenfilename()
jfs
10
Na python2: import Tkinter as tkand import tkFileDialogandfile_path = tkFileDialog.askopenfilename()
SaschaH
9
Nie działa to dobrze w systemie MacOS: okno dialogowe otwiera się, ale przestaje odpowiadać, a cały skrypt zawiesza się.
Konserwacja okresowa,
26

Możesz użyć easygui :

import easygui

path = easygui.fileopenbox()

Aby zainstalować easygui, możesz użyć pip:

pip3 install easygui

Jest to pojedynczy czysty moduł Pythona ( easygui.py), który używa tkinter.

jfs
źródło
6
Projekt easygui został zamknięty, nie jest dalej utrzymywany - obecnie generuje błąd / wyjątek podczas uruchamiania w Pythonie 3.5, być może rozważ inne opcje
pepe
2
@pepe: Nie widzę żadnego powiadomienia w repozytorium projektu (ostatnie zatwierdzenie to 15 maja)
jfs
dobrze wiedzieć, dzięki, może ktoś go odebrał: patrz easygui.wordpress.com/2013/03/06/easygui-project-shuts-down-2
pepe
@Zanam oczywiście to działa. Ale mogą być błędy .
jfs
Jeśli masz problemy z połączeniem tkinter + matplotlib, może to uratować Twój dzień!
Cuong Truong Huy
20

Spróbuj z 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')
FogleBird
źródło
5

Jeśli nie potrzebujesz interfejsu użytkownika lub oczekujesz, że program będzie działał w interfejsie CLI, możesz przeanalizować ścieżkę pliku jako argument. Umożliwiłoby to skorzystanie z funkcji autouzupełniania interfejsu wiersza polecenia, aby szybko znaleźć potrzebny plik.

Byłoby to prawdopodobnie przydatne tylko wtedy, gdyby skrypt nie był interaktywny, poza wejściem ścieżki pliku.

SQDK
źródło
To poprawne rozwiązanie, chociaż czuję się smutny w środku za każdym razem, gdy muszę użyć wiersza poleceń systemu Windows. Pracuję w środowisku Windows.
Buttons840
2
Widzę. Interfejs wiersza polecenia w systemie Windows jest tak zły w porównaniu z Uniksem. Rozumiem, dlaczego selektor plików byłby fajny. Wydaje mi się, że może przeciągnij i upuść plik do skryptu, a następnie odczytaj nazwę pliku jako argument? ( mindlesstechnology.wordpress.com/2008/03/29/… ) Byłoby to o wiele łatwiejsze, gdyby nie wymagało fizycznego skopiowania najpierw pliku. Nie korzystam z bankomatu z systemem Windows, więc nie mogę przetestować, jak się zachowuje. Możesz łatwo wdrożyć hack do rejestru w pliku .reg, jeśli chcesz go zainstalować na kilku komputerach.
SQDK
Alternatywnie, plik .bat może przekazać nazwę pliku do skryptu jako argument. Nie obejmuje to żadnych hacków rejestru.
SQDK
3

Używając tkinter (python 2) lub Tkinter (python 3) rzeczywiście można wyświetlić okno dialogowe otwierania pliku (zobacz inne odpowiedzi tutaj). Należy jednak zauważyć, że interfejs użytkownika tego okna dialogowego jest przestarzały i nie odpowiada nowszym oknom dialogowym otwierania plików dostępnym w systemie Windows 10.

Co więcej - jeśli szukasz sposobu na osadzenie obsługi Pythona we własnej aplikacji - wkrótce przekonasz się, że biblioteka tkinter nie jest kodem typu open source, a co więcej - jest biblioteką komercyjną.

(Na przykład wyszukiwanie „activetcl pricing” prowadzi do tej strony internetowej: https://reviews.financesonline.com/p/activetcl/ )

Tak więc biblioteka tkinter będzie kosztować każdą aplikację, która chce osadzić Pythona.

Samemu udało mi się znaleźć bibliotekę Pythonnet:

(Licencja MIT)

Za pomocą następującego polecenia można zainstalować pythonnet:

pip3 install pythonnet

Tutaj możesz znaleźć działający przykład korzystania z okna dialogowego otwierania pliku:

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

Podam tutaj przykład:

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)

Jeśli brakuje Ci również bardziej złożonego interfejsu użytkownika - zobacz folder Demo w pythonnet git.

Nie jestem pewien co do przenośności na inne systemy operacyjne, nie próbowałem, ale planowane jest przeniesienie .net 5 na wiele systemów operacyjnych (Wyszukaj „.net 5 platform”, https://devblogs.microsoft.com/dotnet/introducing -net-5 / ) - więc ta technologia jest również przyszłościowa.

TarmoPikaro
źródło
2

pywin32zapewnia dostęp do GetOpenFileNamefunkcji win32. Z przykładu

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
Kevin Smyth
źródło
Zmieniło to mój bieżący katalog roboczy na katalog, z którego pobierane są pliki. Co w takim razie zrobić?
Mooncrater
@Mooncrater dodaj |win32con.OFN_NOCHANGEDIRdo Flags, ale uważaj na zastrzeżenie stackoverflow.com/questions/50468051/ ...
Kevin Smyth
Hej, dzięki za sugestię. Skończyło się na tym, że za każdym razem wracałem do oryginalnego katalogu GetOpenFileNameW.
Mooncrater