Как правильно обрабатывать строки Unicode Python с нулевыми байтами? - PullRequest
10 голосов
/ 06 апреля 2011

Вопрос

Похоже, что PyWin32 удобен для предоставления в качестве возвращаемых значений строк Юникода с нулем в конце.Я хотел бы иметь дело с этими строками «правильным» способом.

Допустим, я получаю строку вроде: u'C:\\Users\\Guest\\MyFile.asy\x00\x00sy'.Похоже, это строка с нулевым символом в конце в стиле C, висящая в объекте Unicode Python.Я хочу обрезать этого плохого парня до обычной строки символов, которую я мог бы, например, отобразить в строке заголовка окна.

Обрезает строку в первом нулевом байте правильным способомиметь дело с этим?

Я не ожидал получить возвращаемое значение, как это, поэтому мне интересно, если я упускаю что-то важное о том, как Python, Win32 и Unicode играют вместе ... или этопросто ошибка PyWin32.

Фон

Я использую функцию выбора файлов Win32 GetOpenFileNameW из пакета PyWin32.Согласно документации, эта функция возвращает кортеж, содержащий полный путь к имени файла, как объект Unicode Python.

Когда я открываю диалог с существующим путем и набором имени файла, я получаю странное возвращаемое значение.

Например, у меня по умолчанию установлено значение: C:\\Users\\Guest\\MyFileIsReallyReallyReallyAwesome.asy

В диалоговом окне я изменил имя на MyFile.asy и нажал кнопку Сохранить.

Полный путь частивозвращаемое значение было: u'C: \ Users \ Guest \ MyFile.asy \ x00wesome.asy'`

Я ожидал, что оно будет: u'C:\\Users\\Guest\\MyFile.asy'

Функция возвращает переработанныйбуфер без обрезки завершающих байтов.Излишне говорить, что остальная часть моего кода не была настроена для обработки строки с нулевым символом в стиле C.

Демонстрационный код

Следующий код демонстрирует нулевое значениеопределяемая строка в возвращаемом значении из GetSaveFileNameW.

Указания: в диалоговом окне измените имя файла на «MyFile.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)

Примечание. Если вы не укоротите имя файла (например, если вы попытаетесь использовать MyFileIsReally.asy), строка будет завершена без нулевого байта.

Среда

64-разрядная версия Windows 7 Professional (без пакета обновления), Python 2.7.1, сборка PyWin32 216

ОБНОВЛЕНИЕ:Артефакт отслеживания PyWin32

Судя по полученным мною комментариям и ответам, вероятно, это ошибка Pywin32, поэтому я отправил артефакт отслеживания .

ОБНОВЛЕНИЕ 2: Исправлено!

Марк Хаммонд сообщил в артефакте трекера, что это действительно ошибка.Исправление было проверено на rev f3fdaae5e93d, так что, надеюсь, это сделает следующий релиз.

Я думаю, что ответ Алекси Тархамо ниже - лучшее решение для версий PyWin32 до исправления.

Ответы [ 3 ]

6 голосов
/ 06 апреля 2011

Я бы сказал, что это ошибка. Правильный способ справиться с этим, вероятно, будет исправление pywin32, но если вы не чувствуете себя достаточно смелым, просто обрежьте его.

Вы можете получить все до первого '\x00' с filename.split('\x00', 1)[0].

2 голосов
/ 06 апреля 2011

Этого не происходит в тестируемой мной версии PyWin32 / Windows / Python;Я не получаю никаких нулей в возвращаемой строке, даже если она очень короткая.Вы можете выяснить, исправляет ли более новая версия одного из перечисленных выше ошибку.

0 голосов
/ 29 апреля 2011

ISTR, что у меня была эта проблема несколько лет назад, затем я обнаружил, что такие функции, связанные с диалогом имени файла Win32, возвращают последовательность 'filename1\0filename2\0...filenameN\0\0', в то же время включая возможные символы мусора в зависимости от буфера, выделенного Windows.

Теперь вы можете предпочесть список вместо необработанного возвращаемого значения, но это будет RFE, а не ошибка.

PS Когда у меня возникла эта проблема, я вполне понимал, почему можно ожидать GetOpenFileNameвозможно, чтобы вернуть список имен файлов, хотя я не мог себе представить, почему GetSaveFileName будет.Возможно, это рассматривается как единообразие API.В любом случае, кого я должен знать?

...