Как мне преобразовать строку в байты в Python? - PullRequest
0 голосов
/ 04 февраля 2019

В моем коде я кодирую строку с помощью utf-8.Я получаю вывод, преобразовываю его в строку и отправляю в мою другую программу.Другая программа получает эту строку, но, когда я пытаюсь декодировать строку, она выдает мне ошибку, AttributeError: у объекта 'str' нет атрибута 'decode'.Мне нужно отправить закодированные данные в виде строки, потому что моя другая программа получает их в формате JSON.Моя первая программа на Python 3, а другая на Python 2.

# my first program
x = u"宇宙"
x = str(x.encode('utf-8'))


# my other program
text = x.decode('utf-8')
print(text)

Что мне нужно сделать, чтобы преобразовать строку, полученную второй программой, в байты, чтобы декодирование работало?

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

Самая важная часть для правильного ответа на это - информация о как передать эти объекты программе Python2: вы используете JSON.

Итак, оставайтесь со мной:

После выполнения шага .encode в программе 1 у вас есть объект байтов.Вызывая str(...) для него, вы просто помещаете экранирующий слой в этот объект байтов и возвращаете его обратно в строку - но когда эта строка записывается как есть в файл или передается по сети, она будет закодированаопять же - любые токены не ASCII обычно экранируются с префиксом \u и кодовой точкой для каждого символа - но сами оригинальные китайские символы теперь кодируются в utf-8 и дважды экранируются.

Методы загрузки JSON Python уже декодируют содержимое данных json в текстовые строки: поэтому метод декодирования вообще не ожидается.

Короче говоря : для передачи данных просто закодируйте исходный текст как JSON в первой программе и не занимайтесь декодированием после json.load в целевой программе Python 2:

# my first program
x = "宇宙"
# No str-encode-decode dance needed here.
...
data =  json.dumps({"example_key": x, ...})
# code to transmit json string by network or file as it is...


# my other program
text = json.loads(data)["example_key"]
# text is a Unicode text string ready to be used!

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

In [1]: import json

In [2]: x = "宇宙"

In [3]: print(x.encode("utf-8"))
b'\xe5\xae\x87\xe5\xae\x99'

In [4]: text = str(x.encode("utf-8"))

In [5]: print(text)
b'\xe5\xae\x87\xe5\xae\x99'

In [6]: json_data = json.dumps(text)

In [7]: print(json_data)
"b'\\xe5\\xae\\x87\\xe5\\xae\\x99'"
# as you can see, it is doubly escaped, and it is mostly useless in this form

In [8]: recovered_from_json = json.loads(json_data)

In [9]: print(recovered_from_json)
b'\xe5\xae\x87\xe5\xae\x99'

In [10]: print(repr(recovered_from_json))
"b'\\xe5\\xae\\x87\\xe5\\xae\\x99'"

In [11]: # and if you have data like this in files/databases you need to recover:

In [12]: import ast

In [13]: recovered_text = ast.literal_eval(recovered_from_json).decode("utf-8")

In [14]: print(recovered_text)
宇宙
0 голосов
/ 04 февраля 2019

В основном вы имеете дело с двумя разными версиями Python, и у нее есть проблема с библиотекой.

шесть библиотека решает эту проблему.

Six предоставляет простые утилитыдля переноса различий между Python 2 и Python 3. Он предназначен для поддержки баз кода, которые работают на Python 2 и 3. без изменений.

использует эту библиотеку и декодирует таким образом.

import six

def bytes_to_str(s, encoding='utf-8'):
    """Returns a str if a bytes object is given."""
    if six.PY2 and isinstance(s, bytes):
        return s.decode(encoding)
    return s

text = bytes_to_str(x)
print(text)
...