Boîte de dialogue de fichier rapide et facile en Python?

105

J'ai un script simple qui analyse un fichier et charge son contenu dans une base de données. Je n'ai pas besoin d'interface utilisateur, mais pour le moment, j'invite l'utilisateur à analyser le fichier en utilisant raw_inputce qui est le plus hostile, en particulier parce que l'utilisateur ne peut pas copier / coller le chemin. Je voudrais un moyen rapide et facile de présenter une boîte de dialogue de sélection de fichier à l'utilisateur, il peut sélectionner le fichier, puis il est chargé dans la base de données. (Dans mon cas d'utilisation, s'ils choisissaient le mauvais fichier, l'analyse échouerait et ne poserait pas de problème même s'il était chargé dans la base de données.)

import tkFileDialog
file_path_string = tkFileDialog.askopenfilename()

Ce code est proche de ce que je veux, mais il laisse un cadre vide ennuyeux ouvert (qui ne peut pas être fermé, probablement parce que je n'ai pas enregistré de gestionnaire d'événements de fermeture).

Je n'ai pas besoin d'utiliser tkInter, mais comme il est dans la bibliothèque standard Python, c'est un bon candidat pour la solution la plus rapide et la plus simple.

Quel est le moyen rapide et facile de demander un fichier ou un nom de fichier dans un script sans aucune autre interface utilisateur?

Boutons840
la source
Correction mineure: vous pouvez coller dans un terminal (on dirait que vous êtes sous Windows) en cliquant avec le bouton droit de la souris dans la zone de texte et en sélectionnant "Coller" dans le menu contextuel.
Deestan
1
Aucun menu contextuel n'est disponible dans une invite Python raw_input.
Buttons840
2
raw_input se produit dans le terminal, qui dispose d'un menu contextuel.
Deestan

Réponses:

202

Tkinter est le moyen le plus simple si vous ne souhaitez pas avoir d'autres dépendances. Pour afficher uniquement la boîte de dialogue sans aucun autre élément de l'interface graphique, vous devez masquer la fenêtre racine en utilisant la withdrawméthode:

import tkinter as tk
from tkinter import filedialog

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

file_path = filedialog.askopenfilename()

Variante Python 2:

import Tkinter, tkFileDialog

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

file_path = tkFileDialog.askopenfilename()
tomvodi
la source
3
Cela devrait être la réponse acceptée. C'est simple, efficace et tant que vous ne créez pas de nouvelles fenêtres root Tk encore et encore, c'est bien (et sans mentionner que c'est exactement la réponse que je cherchais quand je suis tombé sur ce fil).
Andrew
2
Je viens de l'utiliser également pour mon travail. Cela fonctionne bien sur Fedora, mais sur Ubuntu, cela gâche tous les chiffres de matplotlib qui suivent. Quasiment après pylab.show (), il se bloque. Je suis toujours capable de taper dans le terminal, mais rien ne se passe. Le processeur passe également à 0% pour mon programme. Aucun conseil?
Diana
17
Sur python3:tkinter.filedialog.askopenfilename()
jfs
10
Sur python2: import Tkinter as tkand import tkFileDialogandfile_path = tkFileDialog.askopenfilename()
SaschaH
8
Cela ne fonctionne pas bien sur MacOS: la boîte de dialogue s'ouvre mais ne répond plus et tout le script se bloque.
Maintenance périodique le
26

Vous pouvez utiliser easygui :

import easygui

path = easygui.fileopenbox()

Pour l'installer easygui, vous pouvez utiliser pip:

pip3 install easygui

C'est un seul module Python pur ( easygui.py) qui utilise tkinter.

jfs
la source
6
Le projet easygui s'est arrêté, pas plus maintenu - il génère actuellement une erreur / exception lors de l'exécution sur Python 3.5, envisagez peut-être d'autres options
pepe
2
@pepe: Je ne vois aucune notification dans le référentiel du projet (le dernier commit est le 15 mai)
jfs
bon à savoir, merci, peut-être que quelqu'un l'a ramassé: voir easygui.wordpress.com/2013/03/06/easygui-project-shuts-down-2
pepe
@Zanam évidemment ça marche. Mais il pourrait y avoir des bugs .
jfs
Si vous avez des problèmes avec le combo tkinter + matplotlib, cela peut vous sauver la journée!
Cuong Truong Huy le
20

Essayez avec 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
la source
5

Si vous n'avez pas besoin de l'interface utilisateur ou que vous vous attendez à ce que le programme s'exécute dans une CLI, vous pouvez analyser le chemin du fichier en tant qu'argument. Cela vous permettrait d'utiliser la fonction de saisie semi-automatique de votre CLI pour trouver rapidement le fichier dont vous avez besoin.

Cela ne serait probablement pratique que si le script n'est pas interactif en plus de l'entrée du chemin de fichier.

SQDK
la source
C'est une solution valable, même si je me sens triste à chaque fois que je dois utiliser la ligne de commande Windows. Je suis dans un environnement Windows.
Buttons840
2
Je vois. La CLI sous Windows est si mauvaise comparée à Unix. Je vois pourquoi un sélecteur de fichiers serait bien. Je suppose que peut-être glisser-déposer le fichier sur le script, puis lire le nom de fichier comme argument? ( mindlesstechnology.wordpress.com/2008/03/29/… ) Cela rendrait les choses beaucoup plus faciles si cela n'implique pas de copier physiquement le fichier en premier. Je ne suis pas sur un guichet automatique Windows, donc je ne peux pas tester son comportement. Vous pouvez facilement déployer le hack de registre dans un fichier .reg si vous devez l'installer sur plusieurs machines.
SQDK
Vous pouvez également demander à un fichier .bat de transmettre le nom de fichier au script en tant qu'argument. Cela n'implique aucun piratage de registre.
SQDK
1

pywin32donne accès à la GetOpenFileNamefonction win32. De l' exemple

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
la source
1

En utilisant tkinter (python 2) ou Tkinter (python 3), il est en effet possible d'afficher une boîte de dialogue d'ouverture de fichier (voir d'autres réponses ici). Veuillez noter cependant que l'interface utilisateur de cette boîte de dialogue est obsolète et ne correspond pas aux boîtes de dialogue d'ouverture de fichier plus récentes disponibles dans Windows 10.

De plus - si vous cherchez à intégrer le support de python dans votre propre application - vous découvrirez bientôt que la bibliothèque tkinter n'est pas du code open source et plus encore - c'est une bibliothèque commerciale.

(Par exemple, la recherche de "tarification activetcl" vous mènera à cette page Web: https://reviews.financesonline.com/p/activetcl/ )

Ainsi, la bibliothèque tkinter coûtera de l'argent pour toute application souhaitant intégrer python.

J'ai moi-même réussi à trouver la bibliothèque de pythonnet:

(Licence MIT)

En utilisant la commande suivante, il est possible d'installer pythonnet:

pip3 install pythonnet

Et ici, vous pouvez trouver un exemple de travail pour l'utilisation de la boîte de dialogue Ouvrir un fichier:

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

Permettez-moi de copier un exemple également ici:

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)

Si vous manquez également une interface utilisateur plus complexe - voir Démo dossier dans pythonnet git.

Je ne suis pas sûr de la portabilité vers d'autres systèmes d'exploitation, je n'ai pas essayé, mais .net 5 est prévu pour être porté sur plusieurs systèmes d'exploitation (recherche "plates-formes .net 5", https://devblogs.microsoft.com/dotnet/introducing -net-5 / ) - cette technologie est donc également à l'épreuve du temps.

TarmoPikaro
la source