2015-11-20 2 views
1

Я передаю объект JSON из Chrome в мой stdin приложения Python с помощью функции отправки и отправки сообщений Chrome/JavaScript sendNativeMessage.Почему sys.stdin.read (4) .encode ('utf-8') возвращает более 4 байтов?

Иногда работает нижний код. Другие времена (я верю в более крупные сообщения), это не работает. Я не уверен, что я делаю неправильно, но я скажу, что иногда sys.stdin.read (4) .encode ('utf-8'), кажется, считывает 7 байтов вместо указанных 4 байта, и это когда он ломается с «struct.error: unpack требует байтового объекта длиной 4».

Может кто-нибудь сообщить мне, что я здесь делаю неправильно?

# On Windows, the default I/O mode is O_TEXT. Set this to O_BINARY 
# to avoid unwanted modifications of the input/output streams. 
import os, msvcrt 
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) 
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) 

# Read the message length (first 4 bytes). 
#for line in sys.stdin: 
text_length_bytes = sys.stdin.read(4).encode('utf-8') 

logging.info(text_length_bytes) 

# Unpack message length as 4 byte integer. 
text_length = struct.unpack('i', text_length_bytes)[0] 

logging.info(text_length) 

# Read the text of the message. 
text = json.loads(sys.stdin.read(text_length)) 
+0

Не-ASCII-символы не кодируются как одиночные байты в UTF-8. – user2357112

+0

Должен ли я кодировать их по-другому? Или обрабатывать данные совершенно по-другому? Я немного потерял это - извинения; Я новичок в Python. – flatsix81

+0

@ flatsix81: Если у вас есть упакованное целое число, вы определенно не хотите делать кодировку/декодирование в строке, содержащей упакованное целое число. Прочитайте необработанные байты, как предлагает tommi, затем распакуйте его, затем прочитайте остальную часть сообщения, затем * decode * (т. Е. Преобразуйте байты в unicode), используя utf-8, если они были * закодированы * (т.е. unicode преобразован в байты), используя UTF-8. – Claudiu

ответ

1

Один символ Unicode может состоять из более чем одного байта:

In [4]: len('ü'.encode('utf-8')) 
Out[4]: 2 

Как вы хотите, чтобы декодировать эти 4 байта, как целое, вы, вероятно, хотите, чтобы прочитать их, как байт (вместо ул) из stdin в первую очередь:

In [8]: type(sys.stdin.read(4)) 
aoeu 
Out[8]: str 

In [9]: type(sys.stdin.buffer.read(4)) 
aoeu 
Out[9]: bytes 
+0

Это сработало! Удивительно. Я часами бил головой о стол, пытаясь разрешить это. Еще раз спасибо! – flatsix81