117

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?

Buttons840
  • 8,107
  • 14
  • 50
  • 81

6 Answers6

230

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()
jfs
  • 346,887
  • 152
  • 868
  • 1,518
tomvodi
  • 4,567
  • 2
  • 25
  • 37
  • 4
    This should be the accepted answer. It's simple, effective, and as long as you're not creating new Tk root windows over and over, it's fine (and not to mention that it's exactly the answer I was looking for when I came across this thread). – Andrew Jan 15 '13 at 12:45
  • 2
    I just used this for my work as well. It works fine on Fedora, but on Ubuntu it messes up any matplotlib figures that follow. Pretty much after pylab.show() it hangs. I'm still able to type in the terminal, but nothing happens. Also cpu goes to 0% for my program. Any advice? – Diana Jul 02 '13 at 20:00
  • 18
    On python3: `tkinter.filedialog.askopenfilename()` – jfs Mar 03 '14 at 20:37
  • 10
    On python2: `import Tkinter as tk` and `import tkFileDialog` and `file_path = tkFileDialog.askopenfilename()` – SaschaH Jun 08 '16 at 17:15
  • 9
    This does not work well on MacOS: the dialog opens but becomes unresponsive and the whole script hangs. – Periodic Maintenance Jun 14 '17 at 07:49
  • @SaschaH Please make that a separate answer – StephenBoesch Aug 14 '17 at 07:09
  • @J.F.Sebastian I responded to wrong person - it was about the python2 code: that was helpful – StephenBoesch Aug 14 '17 at 07:10
  • Related: [TKinter (filedialog.askdirectory) freezing Spyder console](https://stackoverflow.com/q/50158218/4975230) – jrh Jun 26 '19 at 22:30
  • Tkinter is commertial library - will not play for you if you want to embedd python support into your own application. (Meaning you will need to pay for using active TCL library) – TarmoPikaro Nov 14 '19 at 16:42
  • I have a problem when I use this method : the window appears on the back of all the others opened windows – rafalou38 Apr 23 '20 at 18:14
  • For selecting multiple files at once, you can simply replace `askopenfilename` to `askopenfilenames`. – Mooncrater Aug 24 '20 at 09:57
31

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.

nbro
  • 12,226
  • 19
  • 85
  • 163
jfs
  • 346,887
  • 152
  • 868
  • 1,518
  • 7
    easygui project has shut down, not further maintained -- it currently throws an error/exception when running on Python 3.5, perhaps consider other options – pepe Jun 18 '16 at 18:04
  • 2
    @pepe: I don't see any notice in [the project repository](https://github.com/robertlugg/easygui) (the latest commit is May 15) – jfs Jun 18 '16 at 18:35
  • good to know, thx, perhaps someone picked it up: see https://easygui.wordpress.com/2013/03/06/easygui-project-shuts-down-2/ – pepe Jun 18 '16 at 18:42
  • @Zanam obviously it does work. But there could be [bugs](https://github.com/robertlugg/easygui/issues/113). – jfs Oct 09 '16 at 18:14
  • If you guys have trouble with tkinter + matplotlib combo, it can save your day! – Cuong Truong Huy Jan 31 '20 at 13:48
22

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')
nbro
  • 12,226
  • 19
  • 85
  • 163
FogleBird
  • 65,535
  • 24
  • 118
  • 129
5

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.

TarmoPikaro
  • 3,568
  • 1
  • 32
  • 42
  • this solution is only for Windows. Install on linux .NET. o just use FileOpen dialog from python? Laughable... – Reishin Feb 21 '21 at 23:29
  • Haven't tried yet. python .net needs to be ported to .net core, and after that also file open dialog as well. Not sure when this will happen. Need to try out what current technologies are offering. – TarmoPikaro Feb 22 '21 at 09:35
5

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.

SQDK
  • 3,167
  • 3
  • 16
  • 16
  • This is a valid solution, although I feel sad inside every time I have to use the Windows command line. I'm in a Windows environment. – Buttons840 Feb 16 '12 at 21:49
  • 2
    I see. The CLI in Windows is so bad compared to Unix. I see why a file picker would be neat. I guess maybe drag-and-dropping the file onto the script and then reading the filename as the argument? (http://mindlesstechnology.wordpress.com/2008/03/29/make-python-scripts-droppable-in-windows/) That would make it alot easier if it doesn't involve physically copying the file first. I'm not on a Windows box ATM so i can't test how it behaves. You could easily deploy the registry hack in a .reg file if you need to install it on several machines. – SQDK Feb 16 '12 at 22:47
  • Alternatively you can have a .bat file pass the filename to the script as an argument. This doesn't involve any registry hacks. – SQDK Feb 16 '12 at 22:52
4

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

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
  • 1,747
  • 17
  • 19
  • This changed my current working directory, to the directory from which the files are picked. What to do in that case? – Mooncrater Sep 04 '20 at 06:57
  • @Mooncrater add `|win32con.OFN_NOCHANGEDIR` to `Flags`, but beware of caveat https://stackoverflow.com/questions/50468051/how-to-prevent-getopenfilename-from-changing-the-current-directory-while-the-dia – Kevin Smyth Sep 04 '20 at 14:38
  • Hey, thanks for the suggestion. What I ended up doing is reverting to the original directory, every time I used `GetOpenFileNameW`. – Mooncrater Sep 05 '20 at 15:32