Quick and easy file dialog in Python?

Question:

I have a simple script which parses a file and loads it’s contents to a database. I don’t need a UI, but right now I’m prompting the user for the file to parse using raw_input which is most unfriendly, especially because the user can’t copy/paste the path. I would like a quick and easy way to present a file selection dialog to the user, they can select the file, and then it’s loaded to the database. (In my use case, if they happened to chose the wrong file, it would fail parsing, and wouldn’t be a problem even if it was loaded to the database.)

import tkFileDialog
file_path_string = tkFileDialog.askopenfilename()

This code is close to what I want, but it leaves an annoying empty frame open (which isn’t able to be closed, probably because I haven’t registered a close event handler).

I don’t have to use tkInter, but since it’s in the Python standard library it’s a good candidate for quickest and easiest solution.

Whats a quick and easy way to prompt for a file or filename in a script without any other UI?

Asked By: Buttons840

||

Answers:

If you don’t need the UI or expect the program to run in a CLI, you could parse the filepath as an argument. This would allow you to use the autocomplete feature of your CLI to quickly find the file you need.

This would probably only be handy if the script is non-interactive besides the filepath input.

Answered By: SQDK

You can use easygui:

import easygui

path = easygui.fileopenbox()

To install easygui, you can use pip:

pip3 install easygui

It is a single pure Python module (easygui.py) that uses tkinter.

Answered By: jfs

Try with 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')
Answered By: FogleBird

Tkinter is the easiest way if you don’t want to have any other dependencies.
To show only the dialog without any other GUI elements, you have to hide the root window using the withdraw method:

import tkinter as tk
from tkinter import filedialog

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

file_path = filedialog.askopenfilename()

Python 2 variant:

import Tkinter, tkFileDialog

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

file_path = tkFileDialog.askopenfilename()
Answered By: tomvodi

pywin32 provides access to the GetOpenFileName win32 function. From the example

import win32gui, win32con, os

filter='Python Scripts*.py;*.pyw;*.pysText files*.txt'
customfilter='Other file types*.*'
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
Answered By: Kevin Smyth

Using tkinter (python 2) or Tkinter (python 3) it’s indeed possible to display file open dialog (See other answers here). Please notice however that user interface of that dialog is outdated and does not corresponds to newer file open dialogs available in Windows 10.

Moreover – if you’re looking on way to embedd python support into your own application – you will find out soon that tkinter library is not open source code and even more – it is commercial library.

(For example search for “activetcl pricing” will lead you to this web page: https://reviews.financesonline.com/p/activetcl/)

So tkinter library will cost money for any application wanting to embedd python.

I by myself managed to find pythonnet library:

(MIT License)

Using following command it’s possible to install pythonnet:

pip3 install pythonnet

And here you can find out working example for using open file dialog:

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

Let me copy an example also here:

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)

If you also miss more complex user interface – see Demo folder
in pythonnet git.

I’m not sure about portability to other OS’s, haven’t tried, but .net 5 is planned to be ported to multiple OS’s (Search “.net 5 platforms”, https://devblogs.microsoft.com/dotnet/introducing-net-5/ ) – so this technology is also future proof.

Answered By: TarmoPikaro

Another os-agnostic option, use pywebview:

import webview

def webview_file_dialog():
    file = None
    def open_file_dialog(w):
        nonlocal file
        try:
            file = w.create_file_dialog(webview.OPEN_DIALOG)[0]
        except TypeError:
            pass  # user exited file dialog without picking
        finally:
            w.destroy()
    window = webview.create_window("", hidden=True)
    webview.start(open_file_dialog, window)
    # file will either be a string or None
    return file

print(webview_file_dialog())

Environment: python3.8.6 on Mac – though I’ve used pywebview on windows 10 before.

Answered By: Daemon

I just stumbled on this little trick for Windows only: run powershell.exe from subprocess.

import subprocess

sys_const = ssfDESKTOP # Starts at the top level
# sys_const = 0x2a # Correct value for "Program Files (0x86)" folder
powershell_browse = "(new-object -COM 'Shell.Application')."
powershell_browse += "BrowseForFolder(0,'window title here',0,sys_const).self.path"

ret = subprocess.run(["powershell.exe",powershell_browse], stdout=subprocess.PIPE)
print(ret.stdout.decode())

Note the optional use of system folder constants. (There’s an obscure typo in shldisp.h that the "Program Files (0x86)" constant was assigned wrong. I added a comment with the correct value. Took me a bit to figure that one out.)

More info below:

System folder constants

Answered By: Kiki Jewell
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.