Як перетворити між байтами та рядками в Python 3?


78

Це питання типу Python 101, але це мене збентежило на деякий час, коли я спробував використати пакет, який, здавалося, перетворив мій вхідний рядок у байти.

Як ви побачите нижче, я знайшов для себе відповідь, але я відчував, що варто це робити тут, оскільки мені знадобився час, щоб розкопати те, що відбувається. Здається, це загальний для Python 3, тому я не посилався на оригінальний пакет, з яким я грав; здається, це не помилка (просто те, що конкретний пакет мав .tostring()метод, який явно не давав того, що я розумів як рядок ...)

Моя тестова програма виглядає так:

import mangler                                 # spoof package

stringThing = """
<Doc>
    <Greeting>Hello World</Greeting>
    <Greeting>你好</Greeting>
</Doc>
"""

# print out the input
print('This is the string input:')
print(stringThing)

# now make the string into bytes
bytesThing = mangler.tostring(stringThing)    # pseudo-code again

# now print it out
print('\nThis is the bytes output:')
print(bytesThing)

Результат цього коду дає таке:

This is the string input:

<Doc>
    <Greeting>Hello World</Greeting>
    <Greeting>你好</Greeting>
</Doc>


This is the bytes output:
b'\n<Doc>\n    <Greeting>Hello World</Greeting>\n    <Greeting>\xe4\xbd\xa0\xe5\xa5\xbd</Greeting>\n</Doc>\n'

Отже, потрібно мати можливість конвертувати між байтами та рядками, щоб уникнути того, щоб символи, що не є ascii, перетворювались на gobbledegook.


1
Це питання дає більше деталей у відповіді, але я думаю, що коротша відповідь нижче є більш зрозумілою.
Bobble

Відповіді:


117

'Mangler' у наведеному вище зразку коду робив еквівалент цього:

bytesThing = stringThing.encode(encoding='UTF-8')

Існують інші способи написати це (зокрема, використовуючи bytes(stringThing, encoding='UTF-8'), але наведений вище синтаксис дає зрозуміти, що відбувається, а також що робити, щоб відновити рядок:

newStringThing = bytesThing.decode(encoding='UTF-8')

Коли ми це робимо, вихідний рядок відновлюється.

Зверніть увагу, що використання str(bytesThing)просто транскрибує весь gobbledegook, не перетворюючи його назад у Unicode, якщо ви спеціально не запитуєте UTF-8, а саме str(bytesThing, encoding='UTF-8'). Про помилку не повідомляється, якщо не вказано кодування.


Якщо ви подивитесь на фактичні реалізації методів, то побачите, що utf-8це кодування за замовчуванням, тому ви можете його опустити, враховуючи те, що ви знаєте, що кодування справді є utf-8, тобто stringThing.encode()і bytesThing.decode()буде робити це чудово.
ccpizza

@ccpizza Якщо зробити кодування явним у наведених вище прикладах, набагато зрозуміліше, що відбувається, і IMHO - це хороша практика. Не всі юнікоди - це UTF-8. Це також дозволяє уникнути тихої несправності, згаданої в останньому пункті.
Bobble

повністю згоден; явний краще, ніж неявний, але їм добре знати, що є імпліцитним. Чи використовувати його чи ні - це вже інше питання. Те, що ти не можеш, не означає, що повинен :)
ccpizza

У Python 3 безпечніше використовувати, decode('utf-8', 'backslashreplace')щоб уникнути винятку, якщо кодування невідоме. Не завжди слід припускати UTF-8!
Нагєв

15

У python3 існує bytes()метод, який має той самий формат, що і encode().

str1 = b'hello world'
str2 = bytes("hello world", encoding="UTF-8")
print(str1 == str2) # Returns True

Я нічого про це не читав у документах, але, можливо, я шукав не в потрібному місці. Таким чином, ви можете явно перетворити рядки в байтові потоки і зробити їх більш читабельними, ніж використання encodeі decode, і без необхідності префексу bперед лапками.


4

Це питання типу Python 101,

Це просте запитання, але відповідь на нього не така проста.


У python3 об'єкт "bytes" представляє послідовність байтів, об'єкт "string" - послідовність точок коду Юнікоду.

Для перетворення з "байтів" у "рядок" та зі "рядка" назад у "байти" ви використовуєте функції bytes.decode та string.encode. Ці функції приймають два параметри - кодування та політику обробки помилок.

На жаль, є надзвичайно багато випадків, коли послідовності байтів використовуються для подання тексту, але це не обов'язково чітко визначено, яке кодування використовується. Візьмемо для прикладу імена файлів в Unix-подібних системах, що стосується ядра, то це послідовність байтів з декількома спеціальними значеннями, на більшості сучасних дистрибутивів більшість імен файлів будуть UTF-8, але немає гарантії, що всі імена файлів будуть бути.

Якщо ви хочете написати надійне програмне забезпечення, вам слід ретельно продумати ці параметри. Вам потрібно ретельно продумати, в якому кодуванні повинні знаходитись байти, і як ви будете обробляти випадок, коли вони виявляться недійсною послідовністю байтів для кодування, яке, на вашу думку, має бути. Python за замовчуванням має UTF-8 і помилка на будь-якій послідовності байтів, яка не є допустимою UTF-8.

друк (bytesThing)

Python використовує "repr" як резервне перетворення в рядок. repr намагається створити код python, який відтворить об'єкт. У випадку байтового об'єкта це означає, серед іншого, вихід байтів за межі діапазону ascii для друку.


2

СПРОБУЙТЕ ЦЕ:

StringVariable=ByteVariable.decode('UTF-8','ignore')

ТЕСТУВАТИ ТИП:

print(type(StringVariable))

Тут 'StringVariable' представлений у вигляді рядка. 'ByteVariable' представляють як Byte. Це не важливо ставити під сумнів змінні ..

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.