I've been on the hunt for something like this myself. However, I don't just need directories returned, but a mix of directories and (normal) files. None of the suggestions above would give me that. Besides, the tix solution, when testing, gave me "deprecation" warning and, according to the documentation only returns single directory names.
Installing the tkfilebrowser seemed much too much effort just for testing as, according to the documentation, I wouldn't get a mix of files and directories either.
So, I've written a small (relatively) function, using just modules that should be available in any recent (3.x) Python build environment. Below is a prototype, not very pretty, but it does the trick. As you'll notice I've used the standard tkFileDialog function to get a single directory name returned, when trying to go up from the root directory under Windows, to have access to other drives.
import os
import platform
from tkinter import *
from tkinter import ttk, filedialog as fd
def askopennames(initialDir='.'):
if not initialDir: return ('',[])
curdir = [initialDir]
returnList = []
top = Toplevel()
top.columnconfigure(0, weight=1)
pbtn = Button(top, text="print selection")
def build_tree(dir):
updir = os.path.join(os.path.abspath(dir), '..')
def go_updir():
p = os.path.abspath(updir)
dnp = os.path.dirname(updir)
retdir = fd.askdirectory(initialdir=dnp) \
if os.path.samefile(p, dnp) and \
platform.system() == 'Windows' else p
curdir[0] = retdir if retdir else dnp
build_tree(curdir[0])
tree = ttk.Treeview(top, height=17)
tree.columnconfigure(0, weight=1)
tree.heading('#0', text=updir, anchor='w', command=go_updir)
for c in os.listdir(dir):
iid = tree.insert('', 'end', text=c, open=False)
if os.path.isdir(os.path.join(dir,c)): tree.insert(iid, "end")
tree.grid(row=0, sticky='ew')
pbtn.grid(row=1, sticky='nsew')
def get_selection():
returnList.extend([tree.item(s)['text'] \
for s in tree.selection() if tree.item(s)['text']])
top.destroy()
pbtn['command'] = get_selection
def rebuild_tree(e):
folder = tree.item(tree.focus())['text']
curdir[0] = os.path.join(dir, folder)
tree.destroy()
build_tree(curdir[0])
tree.bind('<<TreeviewOpen>>', rebuild_tree)
build_tree(curdir[0])
top.wait_window()
return (curdir[0], returnList)
root = Tk()
def getDirPath(): print(askopennames('.'))
Button(root, text="ok", font=("Helvetica", "13"),
command=getDirPath).grid(ipadx=100)
root.mainloop()