Преобразовать байты в строку

avatar
Tomas Sedovic
3 марта 2009 в 12:23
3446636
24
2986

Я использую этот код для получения стандартного вывода из внешней программы:

>>> from subprocess import *
>>> command_stdout = Popen(['ls', '-l'], stdout=PIPE).communicate()[0]

Метод communication () возвращает массив байтов:

>>> command_stdout
b'total 0\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2\n'

Однако я хотел бы работать с выводом как с обычной строкой Python. Чтобы я мог напечатать это так:

>>> print(command_stdout)
-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1
-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2

Я думал, что это то, для чего предназначен метод binascii.b2a_qp (), но когда я попробовал его, я снова получил тот же массив байтов:

>>> binascii.b2a_qp(command_stdout)
b'total 0\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2\n'

Как преобразовать байтовое значение обратно в строку? Я имею в виду, используя "батарейки" вместо того, чтобы делать это вручную. И я бы хотел, чтобы с Python 3 все было в порядке.

Источник
Charlie Parker
14 марта 2019 в 22:25
100

почему не работает str(text_bytes)? Мне это кажется странным.

Craig Anderson
31 марта 2019 в 17:32
27

@CharlieParker Потому что str(text_bytes) не может указать кодировку. В зависимости от того, что находится в text_bytes, text_bytes.decode('cp1250) `может привести к совершенно другой строке, чем text_bytes.decode('utf-8').

Charlie Parker
22 апреля 2019 в 23:32
11

поэтому функция str больше не преобразуется в настоящую строку. По какой-то причине нужно явно указать кодировку, мне лень читать почему. Просто преобразуйте его в utf-8 и посмотрите, работает ли ваш код. например var = var.decode('utf-8')

jfs
12 апреля 2020 в 05:11
9

@CraigAnderson: unicode_text = str(bytestring, character_encoding) работает должным образом на Python 3. Хотя unicode_text = bytestring.decode(character_encoding) предпочтительнее, чтобы избежать путаницы с просто str(bytes_obj), который создает текстовое представление для bytes_obj вместо его декодирования в текст: str(b'\xb6', 'cp1252') == b'\xb6'.decode('cp1252') == '¶' и str(b'\xb6') == "b'\\xb6'" == repr(b'\xb6') != '¶'

Ответы (24)

avatar
Aaron Maenpaa
3 марта 2009 в 12:26
4656

Вам необходимо декодировать объект байтов для создания строки:

>>> b"abcde"
b'abcde'

# utf-8 is used here because it is a very common encoding, but you
# need to use the encoding your data is actually in.
>>> b"abcde".decode("utf-8") 
'abcde'
mcherm
18 июля 2011 в 19:48
0

Да, но, учитывая, что это результат выполнения команды Windows, не следует ли вместо этого использовать ".decode ('windows-1252')"?

nikow
3 января 2012 в 15:20
73

Использование "windows-1252" тоже ненадежно (например, для других языковых версий Windows), не лучше ли использовать sys.stdout.encoding?

Wookie88
16 апреля 2013 в 13:27
15

Возможно, это поможет кому-то еще: иногда вы используете массив байтов для e.x. Связь TCP. Если вы хотите преобразовать байтовый массив в строку, отсекающую завершающие символы '\ x00', следующего ответа недостаточно. Затем используйте b'example \ x00 \ x00'.decode ('utf-8'). Strip ('\ x00').

anatoly techtonik
28 апреля 2013 в 14:40
2

Я записал ошибку о ее документировании на bugs.python.org/issue17860 - не стесняйтесь предлагать исправление. Если сложно внести свой вклад - приветствуются комментарии, как улучшить.

CMCDragonkai
16 апреля 2014 в 02:59
0

какие еще варианты декодирования есть у двоичного объекта?

martineau
18 мая 2014 в 20:12
60

В Python 2.7.6 не обрабатывает b"\x80\x02\x03".decode("utf-8") -> UnicodeDecodeError: 'utf8' codec can't decode byte 0x80 in position 0: invalid start byte.

wallyk
27 мая 2015 в 21:21
16

Если содержимое представляет собой случайные двоичные значения, преобразование utf-8 скорее всего завершится ошибкой. Вместо этого см. Ответ @techtonik (ниже) coderhelper.com/a/27527728/198536

user2284570
20 октября 2015 в 23:02
0

@AaronMaenpaa: это не будет работать с массивом, как в python2.

serv-inc
13 ноября 2015 в 10:25
0

@Profpatsch: это вроде как скрыто. См. Ответ ниже для ссылки на документацию. Он также находится в строке документации байтов (help(command_stdout)).

Kevin Shea
9 октября 2017 в 12:03
0

@nikow: небольшое обновление по использованию sys.stdout.encoding - разрешено значение None, что приведет к сбою encode ().

Jessica Warren
1 января 2018 в 21:20
0

У меня есть код для сетевой программы. и его [def dataReceived (self, data): print (f "Полученная цитата: {data}")] его распечатка "полученная цитата: b '\ x00 & C: \\ Users \\. pycharm2016.3 \\ config \ x00 & C : \\ users \\ pycharm \\ system \ x00 \ x03-- 'как мне изменить свой код, чтобы исправить это. КОГДА я напишу print (f "receivequote: {data}". decode (' utf-8 '), что не помогает.

Shayne
4 июля 2018 в 17:39
2

Хотя это, как правило, правильный путь, вы должны быть уверены, что у вас правильная кодировка, иначе ваш код может в конечном итоге вырвать сам себя. Что еще хуже, данные из внешнего мира могут содержать неожиданные кодировки. Библиотека chardet на pypi.org/project/chardet может помочь вам в этом, но, опять же, всегда программируйте защитно, иногда даже chardet может ошибаться, поэтому оберните свой мусор подходящей обработкой исключений.

Shihabudheen K M
27 июля 2018 в 06:46
0

UnicodeDecodeError: кодек utf-8 не может декодировать байт 0x8b в позиции 168: недопустимый начальный байт

Charlie Parker
14 марта 2019 в 22:25
2

почему не работает str(text_bytes)? Мне это кажется странным.

Charlie Parker
14 марта 2019 в 22:29
0

это ожидается? Я получаю AttributeError: 'str' object has no attribute 'decode', но в начале строки стоит буква b: b'(Answer 1 Ack)\n' hu ?!

Íhor Mé
26 июня 2020 в 22:32
0

Пришлось использовать декодирование («латынь») для результата скрипта PHP. В противном случае возникали ошибки, связанные с кодировкой, при использовании print_r или var_dump.

Gabriel Staples
25 марта 2021 в 04:12
0

Официальная документация для этого: для всех операций bytes и bytearray (методы, которые могут быть вызваны для этих объектов), см. Здесь: docs.python.org/3/library/stdtypes. html # bytes-methods. В частности, для bytes.decode() см. Здесь: docs.python.org/3/library/stdtypes.html#bytes.decode.

avatar
Shubhank Gupta
23 февраля 2022 в 12:52
2

Мы можем декодировать объект bytes для создания строки, используя bytes.decode(encoding='utf-8', errors='strict') Для документации. Нажмите здесь

Python3 пример:

byte_value = b"abcde"
print("Initial value = {}".format(byte_value))
print("Initial value type = {}".format(type(byte_value)))
string_value = byte_value.decode("utf-8")
# utf-8 is used here because it is a very common encoding, but you need to use the encoding your data is actually in.
print("------------")
print("Converted value = {}".format(string_value))
print("Converted value type = {}".format(type(string_value)))

Вывод:

Initial value = b'abcde'
Initial value type = <class 'bytes'>
------------
Converted value = abcde
Converted value type = <class 'str'>

ПРИМЕЧАНИЕ. В Python3 тип кодировки по умолчанию — utf-8. Таким образом, <byte_string>.decode("utf-8") можно также записать как <byte_string>.decode()

.
avatar
Gopi
28 декабря 2021 в 09:03
-2

вы хотите декодировать байт в строку

>>> b"abcde"
b'abcde'

# utf-8 is used here because it is a very common encoding, but you
# need to use the encoding your data is actually in.
>>> b"abcde".decode("utf-8") 
'abcde'
avatar
Yasser M
21 октября 2021 в 06:36
8

Если у вас возникла эта ошибка:

'кодек utf-8 не может декодировать байт 0x8a'

, то для преобразования байтов в строку лучше использовать следующий код:

bytes = b"abcdefg"
string = bytes.decode("utf-8", "ignore") 

Наслаждайтесь!

avatar
Aarav Dave
9 июля 2021 в 02:09
0

Декодировать с помощью .decode(). Это расшифрует строку. Передайте 'utf-8') как внутреннее значение.

avatar
Ratul Hasan
18 мая 2021 в 19:07
0

Попробуйте использовать этот; эта функция игнорирует все двоичные файлы без набора символов (например, utf-8) и возвращает чистую строку. Он протестирован на python3.6 и выше.

def bin2str(text, encoding = 'utf-8'):
    """Converts a binary to Unicode string by removing all non Unicode char
    text: binary string to work on
    encoding: output encoding *utf-8"""

    return text.decode(encoding, 'ignore')

Здесь функция принимает двоичный файл и декодирует его (преобразует двоичные данные в символы с использованием предопределенного набора символов Python, а аргумент ignore игнорирует все данные, не являющиеся набором символов, из вашего двоичного файла и, наконец, возвращает желаемое значение string .

Если вы не уверены в кодировке, используйте sys.getdefaultencoding(), чтобы получить кодировку по умолчанию для вашего устройства.

avatar
Victor Choy
19 января 2020 в 08:19
2

попробуйте это

bytes.fromhex('c3a9').decode('utf-8') 
avatar
Boris
7 августа 2019 в 14:15
4

Для вашего конкретного случая «запустить команду оболочки и получить ее вывод в виде текста вместо байтов» в Python 3.7 следует использовать subprocess.run и передать text=True (а также capture_output=True для захвата вывода)

command_result = subprocess.run(["ls", "-l"], capture_output=True, text=True)
command_result.stdout  # is a `str` containing your program's stdout

text раньше назывался universal_newlines и был изменен (ну, псевдоним) в Python 3.7. Если вы хотите поддерживать версии Python до 3.7, передайте universal_newlines=True вместо text=True

avatar
HCLivess
1 июня 2019 в 02:30
2

Если вы хотите преобразовать любые байты, а не только строку, преобразованную в байты:

with open("bytesfile", "rb") as infile:
    str = base64.b85encode(imageFile.read())

with open("bytesfile", "rb") as infile:
    str2 = json.dumps(list(infile.read()))

Однако это не очень эффективно. Это превратит изображение размером 2 МБ в 9 МБ.

avatar
Leonardo Filipe
3 июня 2018 в 22:44
2
def toString(string):    
    try:
        return v.decode("utf-8")
    except ValueError:
        return string

b = b'97.080.500'
s = '97.080.500'
print(toString(b))
print(toString(s))
Dev-iL
4 июня 2018 в 05:37
1

Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, как и / или почему решает проблему, улучшило бы долгосрочную ценность ответа. Помните, что вы отвечаете на вопрос для будущих читателей, а не только для человека, который задает его сейчас! Отредактируйте свой ответ, чтобы добавить пояснение и указать, какие ограничения и допущения применяются. Также не помешает упомянуть, почему этот ответ более уместен, чем другие.

Peter Mortensen
28 сентября 2019 в 11:13
0

Объяснение было бы в порядке.

avatar
wim
31 мая 2018 в 17:52
30

Поскольку этот вопрос на самом деле касается вывода subprocess, у вас есть более прямые подходы. Самым современным было бы использование subprocess.check_output и передача text=True (Python 3.7+) для автоматического декодирования stdout с использованием системной кодировки по умолчанию:

text = subprocess.check_output(["ls", "-l"], text=True)

Для Python 3.6, Popen принимает кодировку ключевое слово:

>>> from subprocess import Popen, PIPE
>>> text = Popen(['ls', '-l'], stdout=PIPE, encoding='utf-8').communicate()[0]
>>> type(text)
str
>>> print(text)
total 0
-rw-r--r-- 1 wim badger 0 May 31 12:45 some_file.txt

Общий ответ на вопрос в заголовке, если вы не имеете дело с выводом подпроцесса, - декодировать байты в текст:

>>> b'abcde'.decode()
'abcde'

Без аргумента будет использоваться sys.getdefaultencoding(). Если ваши данные не sys.getdefaultencoding(), вы должны явно указать кодировку в вызове decode:

>>> b'caf\xe9'.decode('cp1250')
'café'
jfs
27 ноября 2019 в 17:18
0

Декодирование вывода ls с использованием кодировки utf-8 может завершиться ошибкой (см. Пример в моем ответе от 2016 года).

jfs
27 ноября 2019 в 17:18
1

@Boris: если указан параметр encoding, то параметр text игнорируется.

avatar
bers
16 марта 2018 в 13:28
7

При работе с данными из систем Windows (с окончанием строк \r\n) мой ответ:

String = Bytes.decode("utf-8").replace("\r\n", "\n")

Почему? Попробуйте это с многострочным Input.txt:

Bytes = open("Input.txt", "rb").read()
String = Bytes.decode("utf-8")
open("Output.txt", "w").write(String)

Все ваши окончания строк будут удвоены (до \r\r\n), что приведет к появлению дополнительных пустых строк. Функции чтения текста Python обычно нормализуют окончания строк, поэтому в строках используется только \n. Если вы получаете двоичные данные из системы Windows, у Python нет возможности это сделать. Таким образом,

Bytes = open("Input.txt", "rb").read()
String = Bytes.decode("utf-8").replace("\r\n", "\n")
open("Output.txt", "w").write(String)

скопирует исходный файл.

mhlavacka
20 февраля 2019 в 09:45
0

Я так долго искал дополнение .replace("\r\n", "\n"). Это ответ, если вы хотите правильно отображать HTML.

avatar
Broper
22 ноября 2017 в 04:20
15

Если вы должны получить следующее, попробовав decode():

AttributeError: объект 'str' не имеет атрибута 'decode'

Вы также можете указать тип кодировки прямо в приведении:

>>> my_byte_str
b'Hello World'

>>> str(my_byte_str, 'utf-8')
'Hello World'
avatar
Inconnu
18 января 2017 в 07:21
7

Для Python 3 это гораздо более безопасный и питонический подход для преобразования из byte в string:

def byte_to_str(bytes_or_str):
    if isinstance(bytes_or_str, bytes): # Check if it's in bytes
        print(bytes_or_str.decode('utf-8'))
    else:
        print("Object not of byte type")

byte_to_str(b'total 0\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2\n')

Вывод:

total 0
-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1
-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2
cosmicFluke
25 мая 2018 в 19:51
6

1) Как сказал @bodangly, проверка типов вообще не является питонической. 2) Функция, которую вы написали, называется «byte_to_str», что означает, что она вернет str, но печатает только преобразованное значение, и выводит сообщение об ошибке в случае сбоя (но не вызывает исключение). Этот подход также не является питоническим и скрывает предоставленное вами решение bytes.decode.

avatar
jfs
16 ноября 2016 в 09:43
31

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

unicode_text = bytestring.decode(character_encoding)

Пример:

>>> b'\xc2\xb5'.decode('utf-8')
'µ'
Команда

ls может выдавать выходные данные, которые нельзя интерпретировать как текст. Имена файлов в Unix может быть любая последовательность байтов, кроме косой черты b'/' и нуля b'\0':

>>> open(bytes(range(0x100)).translate(None, b'\0/'), 'w').close()

Попытка декодировать такой байтовый суп с использованием кодировки utf-8 вызывает UnicodeDecodeError.

Может быть и хуже. Декодирование может завершиться сбоем и привести к появлению моджибаке если вы используете неправильную несовместимую кодировку:

>>> '—'.encode('utf-8').decode('cp1252')
'—'

Данные повреждены, но ваша программа не знает, что сбой произошло.

Как правило, кодировка символов не включается в саму последовательность байтов. Вы должны передавать эту информацию по внеполосному каналу. Некоторые результаты более вероятны, чем другие, поэтому существует модуль chardet, который может угадать кодировку символов. Один скрипт Python может использовать несколько кодировок символов в разных местах.


ls вывод может быть преобразован в строку Python с помощью os.fsdecode() функция, которая успешна даже для некодируемых имена файлов (он использует sys.getfilesystemencoding() и surrogateescape обработчик ошибок на Unix):

import os
import subprocess

output = os.fsdecode(subprocess.check_output('ls'))

Чтобы получить исходные байты, вы можете использовать os.fsencode().

Если вы передаете параметр universal_newlines=True, то subprocess использует locale.getpreferredencoding(False) для декодирования байтов, например может быть cp1252 в Windows.

Чтобы декодировать поток байтов на лету, io.TextIOWrapper() может использоваться: пример.

В разных командах могут использоваться разные кодировки символов. вывод например dir внутренняя команда (cmd) может использовать cp437. Чтобы расшифровать его вывода, вы можете явно передать кодировку (Python 3.6+):

output = subprocess.check_output('dir', shell=True, encoding='cp437')

Имена файлов могут отличаться от os.listdir() (в котором используется Windows Unicode API), например. '\xb6' можно заменить на '\x14' —Python's Кодек cp437 отображает b'\x14' на управляющий символ U + 0014 вместо U + 00B6 (¶). Для поддержки имен файлов с произвольными символами Unicode см. Декодирование выходных данных PowerShell, которые могут содержать символы Unicode, отличные от ASCII, в строку Python

avatar
lmiguelvargasf
29 июня 2016 в 14:21
106

В Python 3 кодировка по умолчанию "utf-8", поэтому вы можете напрямую использовать:

b'hello'.decode()

, что эквивалентно

b'hello'.decode(encoding="utf-8")

С другой стороны, в Python 2, по умолчанию используется кодировка строки по умолчанию. Таким образом, вы должны использовать:

b'hello'.decode(encoding)

, где encoding - желаемая кодировка.

Примечание : поддержка аргументов ключевых слов была добавлена ​​в Python 2.7.

avatar
eafloresf
1 июня 2016 в 00:03
7

Я сделал функцию для очистки списка

def cleanLists(self, lista):
    lista = [x.strip() for x in lista]
    lista = [x.replace('\n', '') for x in lista]
    lista = [x.replace('\b', '') for x in lista]
    lista = [x.encode('utf8') for x in lista]
    lista = [x.decode('utf8') for x in lista]

    return lista
Taylor Edmiston
11 июня 2017 в 19:04
6

Фактически вы можете связать все вызовы .strip, .replace, .encode и т.д. в одном понимании списка и выполнить итерацию по списку только один раз, а не повторять его пять раз.

JulienD
28 июля 2017 в 07:13
1

@TaylorEdmiston Может быть, это сэкономит на распределении, но количество операций останется прежним.

avatar
serv-inc
13 ноября 2015 в 10:24
25

Хотя ответ @Aaron Maenpaa просто работает, пользователь недавно спросил:

Есть ли способ попроще? 'fhand.read (). decode ("ASCII")' [...] Это так долго!

Вы можете использовать:

command_stdout.decode()

decode() имеет стандартный аргумент:

codecs.decode(obj, encoding='utf-8', errors='strict')

jfs
12 апреля 2020 в 04:39
0

.decode(), использующий 'utf-8', может завершиться ошибкой (выходные данные команды могут использовать другую кодировку символов или даже возвращать некодируемую последовательность байтов). Хотя, если ввод - ascii (подмножество utf-8), то .decode() работает.

avatar
anatoly techtonik
17 декабря 2014 в 14:23
111

Если вы не знаете кодировку, то для чтения двоичного ввода в строку в Python 3 и Python 2 совместимым способом используйте древнюю кодировку MS-DOS CP437:

PY3K = sys.version_info >= (3, 0)

lines = []
for line in stream:
    if not PY3K:
        lines.append(line)
    else:
        lines.append(line.decode('cp437'))

Поскольку кодировка неизвестна, ожидайте, что неанглийские символы будут преобразованы в символы cp437 (английские символы не переводятся, поскольку они совпадают в большинстве однобайтовых кодировок и UTF-8).

Декодирование произвольного двоичного ввода в UTF-8 небезопасно, потому что вы можете получить следующее:

>>> b'\x00\x01\xffsd'.decode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 2: invalid
start byte

То же самое относится к latin-1, который был популярен (по умолчанию?) Для Python 2. См. Пропущенные пункты в макете кодовой страницы - именно здесь Python задыхается от печально известного ordinal not in range.

ОБНОВЛЕНИЕ 20150604 : Ходят слухи, что Python 3 имеет стратегию ошибок surrogateescape для кодирования данных в двоичные данные без потери данных и сбоев, но ему нужны тесты преобразования, [binary] -> [str] -> [binary], чтобы проверить оба производительность и надежность.

ОБНОВЛЕНИЕ 20170116 : Благодаря комментарию Nearoo - есть также возможность убрать все неизвестные байты с косой чертой с помощью обработчика ошибок backslashreplace. Это работает только для Python 3, поэтому даже при использовании этого обходного пути вы все равно будете получать несогласованные выходные данные из разных версий Python:

PY3K = sys.version_info >= (3, 0)

lines = []
for line in stream:
    if not PY3K:
        lines.append(line)
    else:
        lines.append(line.decode('utf-8', 'backslashreplace'))

Подробнее см. Поддержка Unicode в Python .

ОБНОВЛЕНИЕ 20170119 : я решил реализовать декодирование с экранированием косой черты, которое работает как для Python 2, так и для Python 3. Оно должно быть медленнее, чем решение cp437, но должно давать идентичные результаты в каждой версии Python.

# --- preparation

import codecs

def slashescape(err):
    """ codecs error handler. err is UnicodeDecode instance. return
    a tuple with a replacement for the unencodable part of the input
    and a position where encoding should continue"""
    #print err, dir(err), err.start, err.end, err.object[:err.start]
    thebyte = err.object[err.start:err.end]
    repl = u'\\x'+hex(ord(thebyte))[2:]
    return (repl, err.end)

codecs.register_error('slashescape', slashescape)

# --- processing

stream = [b'\x80abc']

lines = []
for line in stream:
    lines.append(line.decode('utf-8', 'slashescape'))
anatoly techtonik
20 февраля 2015 в 09:04
6

Я действительно чувствую, что Python должен предоставить механизм для замены отсутствующих символов и продолжения.

user2284570
20 октября 2015 в 23:02
0

@techtonik: это не будет работать с массивом, как в python2.

anatoly techtonik
22 октября 2015 в 07:25
0

@ user2284570 ты про список? И почему он должен работать на массивах? Особенно массивы поплавков ..

Antonis Kalou
6 июля 2016 в 12:14
2

Вы также можете просто игнорировать ошибки Unicode с помощью b'\x00\x01\xffsd'.decode('utf-8', 'ignore') в python 3.

Nearoo
16 января 2017 в 10:40
3

@anatolytechtonik Существует возможность оставить escape-последовательность в строке и продолжить: b'\x80abc'.decode("utf-8", "backslashreplace") приведет к '\\x80abc'. Эта информация была взята из страницы документации Unicode, которая, похоже, была обновлена ​​с момента написания этого ответа.

anatoly techtonik
16 января 2017 в 14:53
0

@Nearoo обновил ответ. К сожалению, это не работает с Python 2 - см. coderhelper.com/questions/25442954/…

Kevin
3 июня 2019 в 13:58
0

«Декодирование произвольного двоичного ввода в UTF-8 небезопасно ... То же самое и с latin-1». Вы можете остановиться на этом? b'\x00\x01\xffsd'.decode("latin-1") работает без сбоев на моей машине (проверено в 2.7.11 и 3.7.3). Можете ли вы привести пример байтового объекта, который вылетает с ошибкой «порядковый номер вне диапазона», когда вы пытаетесь его декодировать с помощью latin1?

LarsH
22 ноября 2019 в 02:32
0

«Декодирование произвольного двоичного ввода в UTF-8 небезопасно, потому что вы можете получить эту [ошибку].» Часто создание исключения считается более безопасным , чем автоматическое создание неверных символов. Считается безопаснее знать, что ваши данные были повреждены, чем не знать. Вот почему преобразование байта в строку в Python 3 спроектировано именно так. В вашем приложении устойчивость может быть важнее правильности, но мы не можем предполагать этого в целом.

pauldx
22 апреля 2020 в 23:05
0

Извините, я не вижу \ x80 off в окончательном выводе с print (line) b '\ x80abc'. У меня есть данные, подобные приведенным ниже, я не знаю, как можно удалить первые странные символы: bytearray (b '\ x00 \ xfc \ x01 {"seq": 4, "firstname": "Maria", "middlename": "Anne", "lastname ":" Джонс "," доб_год ": 2005," доб_месяц ": 5," пол ":" Ж "," зарплата ": 4000} ')

anatoly techtonik
26 июня 2020 в 11:51
0

@Kevin, можете ли вы попробовать версию Python, которая была активна на Dec 17 '14 at 14:23, когда я писал этот ответ? Это были некоторые из версий Python 2 с Windows, возможно, Vista. Скорее всего, ошибка была исправлена ​​в Python 2.7 перед его заморозкой

Kevin
27 июня 2020 в 15:41
0

Хорошо. Снова при использовании 2.7.11 b'\x00\x01\xffsd'.decode('utf-8') выдает сбой с UnicodeDecodeError, а b'\x00\x01\xffsd'.decode('latin-1') возвращает u'\x00\x01\xffsd'. Полагаю, как и в прошлый раз.

plugwash
24 октября 2020 в 04:40
0

Насколько я понимаю, с серией ISO 8859 определение ISO определяет только печатаемые символы, а не управляющие коды, поэтому вы видите пробелы в таблицах в Википедии. Однако на практике коды 0-31 и 127-159 отображаются в соответствующие управляющие коды Unicode. Таким образом, декодирование произвольных байтов с помощью ISO-8859-1 (также известного как latin1) безопасно (это также относится к некоторым, но не ко всем другим кодировкам серии ISO-8859).

avatar
ContextSwitch
21 января 2014 в 15:31
35

Установите для universal_newlines значение True, то есть

command_stdout = Popen(['ls', '-l'], stdout=PIPE, universal_newlines=True).communicate()[0]
twasbrillig
1 марта 2014 в 22:43
5

Я использовал этот метод, и он работает. Хотя он просто угадывает кодировку на основе пользовательских предпочтений в вашей системе, поэтому он не такой надежный, как некоторые другие варианты. Вот что он делает, ссылаясь на docs.python.org/3.4/library/subprocess.html: «Если universal_newlines имеет значение True, [stdin, stdout и stderr] будут открываться как текстовые потоки в универсальном режиме новой строки с использованием кодировки, возвращаемой локалью. .getpreferredencoding (Ложь) ".

Boris
13 января 2019 в 17:02
2

В 3.7 вы можете (и должны) сделать text=True вместо universal_newlines=True.

avatar
Zhichang Yu
11 января 2014 в 07:15
4

Из sys - Системные параметры и функции :

Для записи или чтения двоичных данных из / в стандартные потоки используйте базовый двоичный буфер. Например, чтобы записать байты в стандартный вывод, используйте sys.stdout.buffer.write(b'abc').

Martijn Pieters♦
1 сентября 2014 в 17:34
3

Канал для подпроцесса уже двоичный буфер. В вашем ответе не указано, как получить строковое значение из результирующего значения bytes.

avatar
Sisso
22 августа 2012 в 12:57
226

Думаю, это простой способ:

>>> bytes_data = [112, 52, 52]
>>> "".join(map(chr, bytes_data))
'p44'
leetNightshade
10 мая 2014 в 00:28
6

Спасибо, ваш метод сработал для меня, а не другой. У меня был некодированный массив байтов, который мне нужно было преобразовать в строку. Пытался найти способ перекодировать его, чтобы расшифровать в строку. Этот метод работает отлично!

Martijn Pieters♦
1 сентября 2014 в 16:25
6

@leetNightshade: но это ужасно неэффективно. Если у вас есть байтовый массив, вам нужно только декодировать.

leetNightshade
1 сентября 2014 в 17:06
16

@Martijn Pieters Я только что провел простой тест с этими другими ответами, выполнив несколько 10000 запусков coderhelper.com/a/3646405/353094 И вышеупомянутое решение на самом деле было намного быстрее каждый раз. Для 10 000 прогонов в Python 2.7.7 требуется 8 мсек, в то время как остальные - 12 мс и 18 мс. Конечно, могут быть некоторые вариации в зависимости от ввода, версии Python и т. Д. Мне это не кажется слишком медленным.

Martijn Pieters♦
1 сентября 2014 в 17:11
0

@leetNightshade: но OP здесь использует Python 3.

leetNightshade
1 сентября 2014 в 17:13
0

@Martijn Pieters Достаточно справедливо. В Python 3.4.1 x86 этот метод занимает 17,01 мс, остальные 24,02 мс и 11,51 мс для байтового массива для преобразования строки. Так что в этом случае он не самый быстрый.

Martijn Pieters♦
1 сентября 2014 в 17:20
0

@leetNightshade: похоже, вы также говорите о целых числах и байтовых массивах, а не о значении bytes (как возвращено Popen.communicate()).

leetNightshade
1 сентября 2014 в 17:28
5

@ Мартин Питерс. Да. Таким образом, это не лучший ответ на основной вопрос, который был задан. И название вводит в заблуждение, не так ли? Он / она хочет преобразовать байтовую строку в обычную строку, а не байтовый массив в строку. Этот ответ подходит для заголовка заданного вопроса.

Martijn Pieters♦
1 сентября 2014 в 17:32
0

@leetNightshade: название действительно может вводить в заблуждение, я отредактирую.

Sasszem
1 октября 2016 в 22:53
0

Он может преобразовывать байты, прочитанные из файла с "rb", в строку, и это удобно, когда вы не знаете кодировку

jfs
16 ноября 2016 в 03:16
5

@Sasszem: этот метод - извращенный способ выражения: a.decode('latin-1') где a = bytearray([112, 52, 52]) («Нет ничего лучше обычного текста». Если вам удалось преобразовать байты в текст строка, то вы использовали некоторую кодировку - latin-1 в данном случае)

Mr_and_Mrs_D
11 октября 2017 в 15:14
7

Для python 3 это должно быть эквивалентно байтам ([112, 52, 52]) - btw bytes - плохое имя для локальной переменной именно потому, что это встроенная функция p3.

Martijn Pieters♦
3 июля 2018 в 12:01
2

@leetNightshade: Для полноты картины: bytes(list_of_integers).decode('ascii') примерно на 1/3 быстрее, чем ''.join(map(chr, list_of_integers)) на Python 3.6.

Sandrocottus
19 июня 2020 в 14:55
0

Большое спасибо за этот ответ. Я везде искал решение, но никто не решил мою проблему. Ваш ответ сделал !!!

avatar
mcherm
18 июля 2011 в 19:51
47

Думаю, вам действительно нужно это:

>>> from subprocess import *
>>> command_stdout = Popen(['ls', '-l'], stdout=PIPE).communicate()[0]
>>> command_text = command_stdout.decode(encoding='windows-1252')

Ответ Аарона был правильным, за исключением того, что вам нужно знать , какую кодировку использовать. И я считаю, что Windows использует windows-1252. Это будет иметь значение только в том случае, если в вашем контенте есть какие-то необычные (не ASCII) символы, но тогда это будет иметь значение.

Между прочим, тот факт, что это имеет значение , является причиной того, что Python перешел на использование двух разных типов для двоичных и текстовых данных: он не может волшебным образом конвертировать между ними, потому что он не знать кодировку, если не скажешь! Единственный способ узнать об этом - это прочитать документацию Windows (или прочитать ее здесь).

jfs
21 февраля 2014 в 17:00
3

open() функция для текстовых потоков или Popen(), если вы ее передадите, universal_newlines=True волшебным образом решит кодировку символов для вас (locale.getpreferredencoding(False) в Python 3.3+).

tripleee
17 февраля 2017 в 07:32
2

'latin-1' - это дословная кодировка со всеми установленными кодовыми точками, поэтому вы можете использовать ее для эффективного чтения байтовой строки в любой тип строки, который поддерживает ваш Python (так дословно на Python 2, в Unicode для Python 3).

jfs
12 апреля 2020 в 05:00
0

@tripleee: 'latin-1' - хороший способ получить моджибаке. Также в Windows есть волшебная замена: на удивление сложно передавать данные из одного процесса в другой без изменений, например. dir: \ xb6 -> \ x14 (пример в конце моего ответа)

avatar
dF.
3 марта 2009 в 12:28
301

Вам необходимо декодировать байтовую строку и преобразовать ее в символьную строку (Unicode).

На Python 2

encoding = 'utf-8'
'hello'.decode(encoding)

или

unicode('hello', encoding)

На Python 3

encoding = 'utf-8'
b'hello'.decode(encoding)

или

str(b'hello', encoding)
Alaa M.
27 февраля 2020 в 14:47
3

В Python 3 что, если строка находится в переменной?

jfs
12 апреля 2020 в 05:03
1

@AlaaM .: то же самое. Если у вас variable = b'hello', то unicode_text = variable.decode(character_encoding)

Alex Hall
19 июля 2020 в 03:41
2

для меня variable = variable.decode() автоматически преобразовал его в строковый формат, который я хотел.

spectras
17 апреля 2021 в 11:12
1

@AlexHall> fwiw, вам может быть интересно узнать, что automagic использует utf8, который является значением по умолчанию для encoding arg, если вы его не предоставляете. См. bytes.decode