如何以“正确”的方式处理带有nullbytes的Python unicode字符串?

2024-09-28 23:38:14 发布

您现在位置:Python中文网/ 问答频道 /正文

问题

PyWin32似乎很乐意将以null结尾的unicode字符串作为返回值。我想用“正确”的方式处理这些字符串。在

假设我得到一个字符串:u'C:\\Users\\Guest\\MyFile.asy\x00\x00sy'。这似乎是一个C风格的空结束字符串挂在Python unicode对象中。我想把这个坏小子精简成一个普通的字符串,比如,在窗口标题栏中显示。在

在第一个空字节处修剪字符串是正确的处理方法吗?在

我没想到会得到这样的返回值,所以我想知道我是否遗漏了一些关于Python、Win32和unicode如何协同工作的重要信息。。。或者这只是一个PyWin32错误。在

背景

我正在使用PyWin32包中的Win32文件选择器函数^{}。根据文档,此函数返回一个元组,该元组包含Python unicode对象的完整文件名路径。在

当我用现有的路径和文件名集打开对话框时,我得到一个奇怪的返回值。在

例如,我将默认设置为:C:\\Users\\Guest\\MyFileIsReallyReallyReallyAwesome.asy

在对话框中,我将名称改为MyFile.asy,然后单击保存。在

返回值的完整路径部分是:u'C:\Users\Guest\我的文件.asy\x00型韦索姆。阿西'`

我希望它是:u'C:\\Users\\Guest\\MyFile.asy'

函数返回一个回收的缓冲区而不删减终止字节。不用说,我的其余代码并不是为处理C风格的以null结尾的字符串而设置的。在

演示代码

下面的代码演示GetSaveFileNameW返回值中以null结尾的字符串。在

说明:在对话框中,将文件名改为'我的文件.asy'然后单击“保存”。观察控制台上打印的内容。我得到的输出是u'C:\\Users\\Guest\\MyFile.asy\x00wesome.asy'。在

import win32gui, win32con

if __name__ == "__main__":
    initial_dir = 'C:\\Users\\Guest'
    initial_file = 'MyFileIsReallyReallyReallyAwesome.asy'
    filter_string = 'All Files\0*.*\0'
    (filename, customfilter, flags) = \
        win32gui.GetSaveFileNameW(InitialDir=initial_dir,
                    Flags=win32con.OFN_EXPLORER, File=initial_file,
                    DefExt='txt', Title="Save As", Filter=filter_string,
                    FilterIndex=0)
    print repr(filename)

注意:如果文件名不够短(例如,如果您尝试我的文件是really.asy)字符串将是完整的,没有空字节。在

环境

Windows 7 Professional 64位(无服务包)、Python 2.7.1、PyWin32 Build 216

更新:PyWin32 Tracker工件

根据我目前收到的评论和答案,这很可能是一个pywin32错误,所以我提交了一个tracker artifact。在

更新2:修复!

马克·哈蒙德在《追踪器人工制品》中报告说,这确实是一个bug。修订版f3fdaae5e93d中签入了一个修复程序,因此希望这将成为下一个版本。在

我认为Aleksi Torhamo下面的答案是修复之前PyWin32版本的最佳解决方案。在


Tags: 文件函数字符串字节文件名结尾unicodemyfile
3条回答

我几年前就遇到过这个问题,然后我发现这种与Win32文件名对话框相关的函数返回一个'filename1\0filename2\0...filenameN\0\0'序列,同时根据Windows分配的缓冲区包含可能的垃圾字符。在

现在,您可能希望使用列表而不是原始返回值,但这将是一个RFE,而不是一个bug。在

PS当我遇到这个问题时,我非常理解为什么人们期望GetOpenFileName可能返回一个文件名列表,而我无法想象{}为什么会这样。也许这被认为是API的一致性。我该知道谁呢?在

我得说这是个虫子。解决这个问题的正确方法可能是修复pywin32,但是如果你觉得不够冒险,就修改它。在

您可以使用filename.split('\x00', 1)[0]获得第一个'\x00'之前的所有内容。在

在我测试的PyWin32/Windows/Python版本上不会发生这种情况;即使返回的字符串很短,我也不会得到任何空值。您可能会调查以上某个更新版本是否修复了该错误。在

相关问题 更多 >