Schneller und einfacher Dateidialog in Python?


104

Ich habe ein einfaches Skript, das eine Datei analysiert und ihren Inhalt in eine Datenbank lädt. Ich brauche keine Benutzeroberfläche, aber im Moment fordere ich den Benutzer auf, die Datei zu analysieren, raw_inputwas am unfreundlichsten ist, insbesondere weil der Benutzer den Pfad nicht kopieren / einfügen kann. Ich möchte dem Benutzer eine schnelle und einfache Möglichkeit bieten, einen Dateiauswahldialog zu präsentieren. Er kann die Datei auswählen und sie dann in die Datenbank laden. (In meinem Anwendungsfall würde das Parsen fehlschlagen, wenn sie zufällig die falsche Datei auswählen würden, und wäre auch dann kein Problem, wenn sie in die Datenbank geladen würde.)

import tkFileDialog
file_path_string = tkFileDialog.askopenfilename()

Dieser Code entspricht in etwa dem, was ich möchte, lässt jedoch einen nervigen leeren Frame offen (der nicht geschlossen werden kann, wahrscheinlich weil ich keinen Close Event Handler registriert habe).

Ich muss tkInter nicht verwenden, aber da es sich in der Python-Standardbibliothek befindet, ist es ein guter Kandidat für die schnellste und einfachste Lösung.

Was ist eine schnelle und einfache Möglichkeit, eine Datei oder einen Dateinamen in einem Skript ohne andere Benutzeroberfläche anzufordern?


Kleinere Korrektur: Sie können in ein Terminal einfügen (es hört sich so an, als wären Sie unter Windows), indem Sie mit der rechten Maustaste in den Textbereich klicken und im Kontextmenü "Einfügen" auswählen.
Deestan

1
In einer Python raw_input-Eingabeaufforderung ist kein Rechtsklick-Menü verfügbar.
Buttons840

2
raw_input erfolgt im Terminal, das über ein Rechtsklick-Menü verfügt.
Deestan

Antworten:


199

Tkinter ist der einfachste Weg, wenn Sie keine anderen Abhängigkeiten haben möchten. Um nur das Dialogfeld ohne andere GUI-Elemente anzuzeigen, müssen Sie das Stammfenster mit der folgenden withdrawMethode ausblenden :

import tkinter as tk
from tkinter import filedialog

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

file_path = filedialog.askopenfilename()

Python 2-Variante:

import Tkinter, tkFileDialog

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

file_path = tkFileDialog.askopenfilename()

3
Dies sollte die akzeptierte Antwort sein. Es ist einfach, effektiv und solange Sie nicht immer wieder neue Tk-Root-Fenster erstellen, ist es in Ordnung (und ganz zu schweigen davon, dass es genau die Antwort ist, nach der ich gesucht habe, als ich auf diesen Thread gestoßen bin).
Andrew

2
Ich habe das auch nur für meine Arbeit benutzt. Es funktioniert gut unter Fedora, aber unter Ubuntu bringt es alle folgenden Matplotlib-Zahlen durcheinander. Ziemlich genau nach pylab.show () hängt es. Ich kann das Terminal immer noch eingeben, aber es passiert nichts. Auch die CPU geht für mein Programm auf 0%. Irgendein Rat?
Diana

17
Auf python3:tkinter.filedialog.askopenfilename()
JFS

10
Auf Python2: import Tkinter as tkund import tkFileDialogundfile_path = tkFileDialog.askopenfilename()
SaschaH

8
Dies funktioniert unter MacOS nicht gut: Der Dialog wird geöffnet, reagiert jedoch nicht mehr und das gesamte Skript hängt.
Regelmäßige Wartung

26

Sie können easygui verwenden :

import easygui

path = easygui.fileopenbox()

Zur Installation easyguikönnen Sie Folgendes verwenden pip:

pip3 install easygui

Es ist ein einzelnes reines Python-Modul ( easygui.py), das verwendet tkinter.


6
easygui Projekt wurde heruntergefahren, nicht weiter gepflegt - es löst derzeit einen Fehler / eine Ausnahme aus, wenn es unter Python 3.5 ausgeführt wird, vielleicht erwägen Sie andere Optionen
pepe

2
@pepe: Ich sehe keine Notiz in Projekt-Repository (das letzte Commit ist der 15. Mai)
jfs

Gut zu wissen, danke, vielleicht hat es jemand aufgegriffen: siehe easygui.wordpress.com/2013/03/06/easygui-project-shuts-down-2
pepe

@ Zanam offensichtlich funktioniert es. Aber es könnte sein Fehler geben .
JFS

Wenn ihr Probleme mit der Kombination tkinter + matplotlib habt, kann das euren Tag retten!
Cuong Truong Huy

20

Versuchen Sie es mit 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

Wenn Sie die Benutzeroberfläche nicht benötigen oder erwarten, dass das Programm in einer CLI ausgeführt wird, können Sie den Dateipfad als Argument analysieren. Auf diese Weise können Sie die Autovervollständigungsfunktion Ihrer CLI verwenden, um die benötigte Datei schnell zu finden.

Dies wäre wahrscheinlich nur dann nützlich, wenn das Skript neben der Dateipfadeingabe nicht interaktiv ist.


Dies ist eine gültige Lösung, obwohl ich jedes Mal traurig bin, wenn ich die Windows-Befehlszeile verwenden muss. Ich bin in einer Windows-Umgebung.
Buttons840

2
Aha. Die CLI in Windows ist im Vergleich zu Unix so schlecht. Ich verstehe, warum eine Dateiauswahl ordentlich wäre. Ich denke, vielleicht ziehen Sie die Datei per Drag & Drop in das Skript und lesen dann den Dateinamen als Argument? ( mindlesstechnology.wordpress.com/2008/03/29/… ) Das würde es viel einfacher machen, wenn die Datei nicht zuerst physisch kopiert werden müsste. Ich bin nicht an einem Windows-Geldautomaten, daher kann ich nicht testen, wie es sich verhält. Sie können den Registrierungs-Hack problemlos in einer REG-Datei bereitstellen, wenn Sie ihn auf mehreren Computern installieren müssen.
SQDK

Alternativ kann eine .bat-Datei den Dateinamen als Argument an das Skript übergeben. Dies beinhaltet keine Registrierungshacks.
SQDK

2

Schauen Sie sich EasyGUI an, ein sehr einfach zu verwendendes Modul, das die Arbeit erledigen sollte - http://easygui.sourceforge.net/

Sie würden die auf dieser API-Dokumentationsseite beschriebene Funktion fileopenbox verwenden - https://easygui.readthedocs.io/en/latest/api.html


1
Entschuldigung - auf meinem Handy kann ich kein Beispiel geben. Sie möchten, dass die Datei openbox - ferg.org/easygui/easygui.html#-fileopenbox
timc

Der zweite Link ist unterbrochen.
Thomas Andrews

1

pywin32bietet Zugriff auf die GetOpenFileNamewin32-Funktion. Aus dem Beispiel

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

1

Mit tkinter (Python 2) oder Tkinter (Python 3) ist es tatsächlich möglich, den Dialog zum Öffnen von Dateien anzuzeigen (siehe andere Antworten hier). Beachten Sie jedoch, dass die Benutzeroberfläche dieses Dialogfelds veraltet ist und nicht den neueren Dialogfeldern zum Öffnen von Dateien entspricht, die in Windows 10 verfügbar sind.

Wenn Sie auf dem Weg sind, die Python-Unterstützung in Ihre eigene Anwendung einzubetten, werden Sie bald feststellen, dass es sich bei der tkinter-Bibliothek nicht um Open Source-Code handelt, sondern um eine kommerzielle Bibliothek.

(Wenn Sie beispielsweise nach "activetcl price" suchen, gelangen Sie zu dieser Webseite: https://reviews.financesonline.com/p/activetcl/ )

Die tkinter-Bibliothek kostet also Geld für jede Anwendung, die Python einbetten möchte.

Ich selbst habe es geschafft, eine Pythonnet-Bibliothek zu finden:

(MIT-Lizenz)

Mit dem folgenden Befehl ist es möglich, Pythonnet zu installieren:

pip3 install pythonnet

Und hier finden Sie ein Arbeitsbeispiel für die Verwendung des Dialogfelds zum Öffnen von Dateien:

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

Lassen Sie mich auch hier ein Beispiel kopieren:

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)

Wenn Sie auch eine komplexere Benutzeroberfläche vermissen, lesen Sie Demo lesen Ordner in Pythonnet Git.

Ich bin mir nicht sicher, ob es auf andere Betriebssysteme portierbar ist, habe es noch nicht versucht, aber .net 5 soll auf mehrere Betriebssysteme portiert werden (Suche nach ".net 5-Plattformen", https://devblogs.microsoft.com/dotnet/introducing) -net-5 / ) - diese Technologie ist also auch zukunftssicher.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.