Страницы

Поиск по вопросам

воскресенье, 7 июля 2019 г.

При запуске subprocess команды с кириллицей происходит ошибка: UnicodeEncodeError: 'ascii' codec can't encode

# -*- coding: utf-8 -*- from __future__ import unicode_literals import argparse import ctypes import subprocess parser = argparse.ArgumentParser(description='test') parser.add_argument('-f', help = 'folder') args = parser.parse_args() path = args.f if ctypes.windll.shell32.IsUserAnAdmin() != 0: print 'You admin
' output = subprocess.check_output(['takeown', '/F', path, '/R', '/A']) print output output2 = subprocess.check_output(['icacls', path, '/grant:r', 'Администраторы:F']) print output2 else: print 'You not admin' exit(0)
Как отобразить? "Администраторы"


Ответ

Почему UnicodeEncodeError при вызове subprocess.check_output()
Traceback показывает, что subproces.check_output() вызывает subprocess.Popen, которая на Windows вызывает _subprocess.CreateProcess на Питоне 2
Благодаря from __future__ import unicode_literals директиве: 'abc' у вас имеет unicode тип (Python 2).
sp_CreateProcess преобразует unicode аргумент в байты (char*), используя 'z' формат, который использует кодировку по умолчанию (sys.getdefaultencoding() == 'ascii' на Питоне 2). См. Parsing arguments and building values
Так как используется CreateProcessA() WinAPI (не Unicode) на Windows в Питоне 2, то перед передачей в subprocess, руками попробуйте закодировать не-ascii аргументы, используя ANSI codepage:
args = [u'icacls', path, u'/grant:r', u'Администраторы:F'] args = [arg.encode(sys.getfilesystemencoding()) for arg in args] subprocess.check_call(args)
Почему кракозябры в traceback
На Питоне 2, 'abc' строковая константа (string literal) это последовательность байт, представляющая символы, записанные в исходном коде, в кодировке, указанной наверху файла (# -*- coding: utf-8 -*- -- PEP 263 encoding declaration). from __future__ import unicode_literals директива превращает 'abc' (байты) в u'abc' (unicode).
Кракозябры могут появиться, когда текст, закодированный в одной кодировке, показывается используя другую (несовместимую) кодировку:
>>> print(u'Администраторы:F'.encode('utf-8').decode('cp866')) ╨Р╨┤╨╝╨╕╨╜╨╕╤Б╤В╤А╨░╤В╨╛╤А╤Л:F
Исходный код (utf-8) как байты напрямую без перекодировки выводится в консоль (cp866 здесь), поэтому вы видите кракозябры -- это можно считать багом в Питоне 2.

Комментариев нет:

Отправить комментарий