tkFileDialog不会将结果转换为Windows上的Python列表

时间:2012-02-10 12:34:34

标签: python tkinter tk

我正在使用下面的代码(Python 2.7和Python 3.2)来显示支持多选的“打开文件”对话框。在Linux上,filenames是一个python列表,但在Windows上,文件名返回为{C:/Documents and Settings/IE User/My Documents/VPC_EULA.txt} {C:/Documents and Settings/IE User/My Documents/VPC_ReadMe.txt},即原始TCL列表。

这是一个python错误,这里的任何人都知道将原始TCL列表转换为python列表的好方法吗?

if sys.hexversion >= 0x030000F0:
    import tkinter.filedialog as filedialog
else:
    import tkFileDialog as filedialog

options = {}
options['filetypes'] = [('vnote files', '.vnt') ,('all files', '.*')]
options['multiple'] = 1
filenames = filedialog.askopenfilename(**options)

4 个答案:

答案 0 :(得分:3)

问题是Tcl,Tk和Python之间的“有趣”交互,每个交互都在做一些合理的事情,但是组合行为不正确。深层次的问题是Tcl和Python对于什么类型意味着非常不同的想法,这表现为Tcl看作列表的值,但Python看作是一个字符串(代码在Tk中)假设它不需要小心为Python清理)。可以说,Python界面应该使用这样一个事实:它可以知道一个Tcl列表将从多个选择中返回并隐藏它,但它不会让你被卡住。

我可以(而且应该!)在Tk修复此问题,但我不知道修复程序需要多长时间才能找到回复的方式。


[编辑]:现在已在Tk 8.5维护分支和主开发分支中修复(使用this补丁)。我无法预测何时能够获得固定版本,除非您从我们的化石库中获取源并自行构建它。

答案 1 :(得分:1)

出于某种原因,基于tk_eval的修复程序对我不起作用。 tkFileDialog返回的字符串中的文件名只包含在{}括号中,如果它们包含空格,而tcl文档似乎暗示所有列表项都应该用这些括号分隔。

无论如何,这是一个似乎对我有用的修复(Windows 7上的python 2.7.3):

def fixlist(filenames):
    #do nothing if already a python list
    if isinstance(filenames,list): return filenames

    #http://docs.python.org/library/re.html
    #the re should match: {text and white space in brackets} AND anynonwhitespacetokens
    #*? is a non-greedy match for any character sequence
    #\S is non white space

    #split filenames string up into a proper python list
    result = re.findall("{.*?}|\S+",filenames)

    #remove any {} characters from the start and end of the file names
    result = [ re.sub("^{|}$","",i) for i in result ]

    return result

答案 2 :(得分:0)

此修复程序适用于我:

if sys.hexversion >= 0x030000F0:
    import tkinter.filedialog as filedialog
    string_type = str
else:
    import tkFileDialog as filedialog
    string_type = basestring

options = {}
options['filetypes'] = [('vnote files', '.vnt') ,('all files', '.*')]
options['multiple'] = 1
filenames = filedialog.askopenfilename(**options)
if isinstance(filenames, string_type):
    # tkinter is not converting the TCL list into a python list...
    # see http://stackoverflow.com/questions/9227859/
    #
    # based on suggestion by Cameron Laird in http://bytes.com/topic/python/answers/536853-tcl-list-python-list
    if sys.hexversion >= 0x030000F0:
        import tkinter
    else:
        import Tkinter as tkinter
    tk_eval = tkinter.Tk().tk.eval
    tcl_list_length = int(tk_eval("set tcl_list {%s}; llength $tcl_list" % filenames))
    filenames = [] # change to a list
    for i in range(tcl_list_length):
        filenames.append(tk_eval("lindex $tcl_list %d" % i))
return filenames

答案 3 :(得分:0)

我用过的一种快捷方式:

filenames = filenames.strip('{}').split('} {')