Diálogo de arquivo rápido e fácil em Python?

104

Eu tenho um script simples que analisa um arquivo e carrega seu conteúdo em um banco de dados. Não preciso de uma IU, mas agora estou solicitando ao usuário que o arquivo analise usando, o raw_inputque é mais hostil, especialmente porque o usuário não pode copiar / colar o caminho. Gostaria de uma maneira rápida e fácil de apresentar ao usuário uma caixa de diálogo de seleção de arquivos, eles podem selecionar o arquivo e, em seguida, carregá-lo no banco de dados. (No meu caso de uso, se eles escolhessem o arquivo errado, haveria falha na análise e não seria um problema, mesmo se fosse carregado no banco de dados.)

import tkFileDialog
file_path_string = tkFileDialog.askopenfilename()

Este código está perto do que eu quero, mas deixa um quadro vazio irritante aberto (que não pode ser fechado, provavelmente porque eu não registrei um manipulador de evento de fechamento).

Não preciso usar tkInter, mas, como está na biblioteca padrão do Python, é um bom candidato para a solução mais rápida e fácil.

Qual é a maneira rápida e fácil de solicitar um arquivo ou nome de arquivo em um script sem qualquer outra IU?

Buttons840
fonte
Correção secundária: você pode colar no terminal a (parece que você está no Windows) clicando com o botão direito na área de texto e selecionando "Colar" no menu de contexto.
Deestan
1
Nenhum menu do botão direito está disponível em um prompt Python raw_input.
Buttons840
2
raw_input acontece no terminal, que tem um menu do botão direito.
Deestan

Respostas:

200

O Tkinter é a maneira mais fácil se você não quiser ter outras dependências. Para mostrar apenas a caixa de diálogo sem quaisquer outros elementos da GUI, você deve ocultar a janela raiz usando o withdrawmétodo:

import tkinter as tk
from tkinter import filedialog

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

file_path = filedialog.askopenfilename()

Variante do Python 2:

import Tkinter, tkFileDialog

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

file_path = tkFileDialog.askopenfilename()
tomvodi
fonte
3
Esta deve ser a resposta aceita. É simples, eficaz e, desde que você não esteja criando novas janelas de raiz do Tk repetidamente, está tudo bem (e sem mencionar que é exatamente a resposta que eu estava procurando quando me deparei com este tópico).
Andrew
2
Eu apenas usei isso para o meu trabalho também. Funciona bem no Fedora, mas no Ubuntu bagunça qualquer figura matplotlib que se segue. Muito bem depois de pylab.show () ele trava. Ainda consigo digitar no terminal, mas nada acontece. Além disso, a cpu vai para 0% no meu programa. Algum conselho?
Diana
17
Em python3:tkinter.filedialog.askopenfilename()
jfs
10
Em python2: import Tkinter as tkand import tkFileDialogandfile_path = tkFileDialog.askopenfilename()
SaschaH
8
Isso não funciona bem no MacOS: a caixa de diálogo é aberta, mas não responde e todo o script trava.
Manutenção periódica de
26

Você pode usar o easygui :

import easygui

path = easygui.fileopenbox()

Para instalar easygui, você pode usar pip:

pip3 install easygui

É um único módulo Python puro ( easygui.py) que usa tkinter.

jfs
fonte
6
O projeto easygui foi encerrado, sem manutenção adicional - atualmente emite um erro / exceção ao ser executado no Python 3.5, talvez considere outras opções
pepe
2
@pepe: Não vejo nenhum aviso no repositório do projeto (o último commit é 15 de maio)
jfs
bom saber, obrigado, talvez alguém o tenha comprado
pepe
@Zanam obviamente funciona. Mas pode haver insetos .
jfs de
Se vocês têm problemas com a combinação tkinter + matplotlib, isso pode salvar o seu dia!
Cuong Truong Huy
20

Experimente com 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
fonte
5

Se você não precisa da IU ou espera que o programa seja executado em uma CLI, você pode analisar o caminho do arquivo como um argumento. Isso permitirá que você use o recurso de preenchimento automático de sua CLI para encontrar rapidamente o arquivo de que precisa.

Isso provavelmente só seria útil se o script não fosse interativo além da entrada do caminho do arquivo.

SQDK
fonte
Esta é uma solução válida, embora eu me sinta triste por dentro sempre que preciso usar a linha de comando do Windows. Estou em um ambiente Windows.
Buttons840
2
Entendo. A CLI no Windows é tão ruim em comparação com o Unix. Eu vejo porque um seletor de arquivos seria legal. Eu acho que talvez arrastar e soltar o arquivo no script e, em seguida, ler o nome do arquivo como o argumento? ( mindlesstechnology.wordpress.com/2008/03/29/… ) Isso tornaria muito mais fácil se não envolver a cópia física do arquivo primeiro. Não estou em um caixa eletrônico do Windows, então não posso testar como ele se comporta. Você pode facilmente implantar o hack do registro em um arquivo .reg se precisar instalá-lo em várias máquinas.
SQDK
Como alternativa, você pode fazer com que um arquivo .bat passe o nome do arquivo para o script como um argumento. Isso não envolve quaisquer hacks de registro.
SQDK
1

pywin32fornece acesso à GetOpenFileNamefunção win32. Do exemplo

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
fonte
1

Usando tkinter (python 2) ou Tkinter (python 3) é realmente possível exibir a caixa de diálogo de abertura de arquivo (veja outras respostas aqui). Observe, entretanto, que a interface do usuário dessa caixa de diálogo está desatualizada e não corresponde às caixas de diálogo de abertura de arquivo mais recentes disponíveis no Windows 10.

Além disso - se você está procurando uma maneira de incorporar o suporte a python em seu próprio aplicativo - você descobrirá logo que a biblioteca tkinter não é um código-fonte aberto e ainda mais - é uma biblioteca comercial.

(Por exemplo, a pesquisa por "preços ativetcl" levará você a esta página da web: https://reviews.financesonline.com/p/activetcl/ )

Portanto, a biblioteca tkinter custará dinheiro para qualquer aplicativo que queira incorporar Python.

Eu mesmo consegui encontrar a biblioteca pythonnet:

(Licença MIT)

Usando o seguinte comando, é possível instalar o pythonnet:

pip3 install pythonnet

E aqui você pode encontrar um exemplo prático para usar a caixa de diálogo de arquivo aberto:

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

Deixe-me copiar um exemplo também aqui:

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)

Se você também sente falta de uma interface de usuário mais complexa - consulte a pasta Demo em pythonnet git.

Não tenho certeza sobre a portabilidade para outros sistemas operacionais, não tentei, mas .net 5 está planejado para ser transferido para vários sistemas operacionais (pesquise ".net 5 plataformas", https://devblogs.microsoft.com/dotnet/introducing -net-5 / ) - portanto, esta tecnologia também é compatível com o futuro.

TarmoPikaro
fonte