Вопрос
Кажется, что PyWin32 комфортно предоставляет строки Unicode с завершающим нулем в качестве возвращаемых значений. Я бы хотел «правильно» обращаться с этими струнами.
Скажем, я получаю строку вида: 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 Build 216
ОБНОВЛЕНИЕ: артефакт трекера PyWin32
Судя по комментариям и ответам, которые я получил до сих пор, это, вероятно, ошибка pywin32, поэтому я отправил артефакт трекера.
ОБНОВЛЕНИЕ 2: исправлено!
Марк Хаммонд сообщил в артефакте трекера, что это действительно ошибка. Было зарегистрировано исправление для rev f3fdaae5e93d, так что, надеюсь, оно будет сделано в следующем выпуске.
Я думаю, что приведенный ниже ответ Алекси Торхамо - лучшее решение для версий PyWin32 до исправления.