O que o caractere 'b' faz na frente de uma string literal?

832

Aparentemente, o seguinte é a sintaxe válida:

my_string = b'The string'

Eu gostaria de saber:

  1. O que esse bcaractere na frente da string significa?
  2. Quais são os efeitos de usá-lo?
  3. Quais são as situações apropriadas para usá-lo?

Eu encontrei uma pergunta relacionada aqui no SO, mas essa pergunta é sobre PHP e afirma que bé usada para indicar que a string é binária, em oposição ao Unicode, que era necessário para que o código fosse compatível com a versão do PHP <6 , ao migrar para o PHP 6. Acho que isso não se aplica ao Python.

Encontrei esta documentação no site Python sobre o uso de um ucaractere na mesma sintaxe para especificar uma string como Unicode. Infelizmente, ele não menciona o caractere b em nenhum lugar desse documento.

Além disso, apenas por curiosidade, há mais símbolos do que o be uque fazer outras coisas?

Jesse Webb
fonte

Respostas:

417

Para citar a documentação do Python 2.x :

Um prefixo de 'b' ou 'B' é ignorado no Python 2; indica que o literal deve se tornar um literal de bytes no Python 3 (por exemplo, quando o código é convertido automaticamente com 2to3). Um prefixo 'u' ou 'b' pode ser seguido por um prefixo 'r'.

A documentação do Python 3 afirma:

Os literais de bytes sempre são prefixados com 'b' ou 'B'; eles produzem uma instância do tipo de bytes em vez do tipo str. Eles podem conter apenas caracteres ASCII; bytes com um valor numérico de 128 ou superior devem ser expressos com escapes.

NPE
fonte
4
Parece que o Python <v3 simplesmente ignora esse caractere extra. Qual seria o caso da v3 em que você precisaria usar uma string ab em vez de apenas uma string regular?
Jesse Webb
5
@ Gweebz - se você estiver digitando uma string em uma codificação específica em vez de com escapes unicode (por exemplo, b '\ xff \ xfe \ xe12' em vez de '\ u32e1').
detly
7
Na verdade, se você importou unicode_literalsa partir __future__, isso vai "reverter" o comportamento para esta corda particular (em Python 2.x)
Romuald Brunet
34
Uma narrativa linguagem pouco mais simples em torno da documentação citada faria este uma resposta melhor IMHO
Hack-R
2
Caso contrário, é uma resposta para alguém que já entende.
Rafael Eyng 18/10/19
680

O Python 3.x faz uma distinção clara entre os tipos:

  • str= '...'literais = uma sequência de caracteres Unicode (UTF-16 ou UTF-32, dependendo de como o Python foi compilado)
  • bytes= b'...'literais = uma sequência de octetos (números inteiros entre 0 e 255)

Se você conhece Java ou C #, pense em strcomo Stringe bytescomo byte[]. Se você conhece o SQL, pense em strcomo NVARCHARe bytescomo BINARYou BLOB. Se você estiver familiarizado com o registro do Windows, pense em strcomo REG_SZe bytescomo REG_BINARY. Se você conhece C (++), esqueça tudo o que aprendeu chare as strings, porque UM PERSONAGEM NÃO É UM BYTE . Essa ideia é obsoleta há muito tempo.

Você usa strquando deseja representar texto.

print('שלום עולם')

Você usa bytesquando deseja representar dados binários de baixo nível, como estruturas.

NaN = struct.unpack('>d', b'\xff\xf8\x00\x00\x00\x00\x00\x00')[0]

Você pode codificar a strpara um bytesobjeto.

>>> '\uFEFF'.encode('UTF-8')
b'\xef\xbb\xbf'

E você pode decodificar a bytesem a str.

>>> b'\xE2\x82\xAC'.decode('UTF-8')
'€'

Mas você não pode misturar livremente os dois tipos.

>>> b'\xEF\xBB\xBF' + 'Text with a UTF-8 BOM'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't concat bytes to str

A b'...'notação é um pouco confusa, pois permite que os bytes 0x01-0x7F sejam especificados com caracteres ASCII em vez de números hexadecimais.

>>> b'A' == b'\x41'
True

Mas devo enfatizar que um personagem não é um byte .

>>> 'A' == b'A'
False

No Python 2.x

As versões pré-3.0 do Python não tinham esse tipo de distinção entre texto e dados binários. Em vez disso, havia:

  • unicode= u'...'literais = sequência de caracteres Unicode = 3.xstr
  • str = '...' literais = sequências de bytes / caracteres confusos
    • Geralmente texto, codificado em alguma codificação não especificada.
    • Mas também usado para representar dados binários como struct.packsaída.

Para facilitar a transição 2.x para 3.x, a b'...'sintaxe literal foi suportada para o Python 2.6, a fim de permitir a distinção entre cadeias binárias (que devem estar bytesem 3.x) e cadeias de texto (que devem estar strem 3 .x). O bprefixo não faz nada no 2.x, mas informa ao2to3 script para não convertê-lo em uma seqüência de caracteres Unicode no 3.x.

Então, sim, b'...'literais em Python têm o mesmo propósito que eles têm em PHP.

Além disso, por curiosidade, existem mais símbolos do que b e u que fazem outras coisas?

O rprefixo cria uma sequência bruta (por exemplo, r'\t'é uma barra invertida + em tvez de uma guia) e aspas triplas '''...'''ou """..."""permite literais de sequências de várias linhas.

dan04
fonte
2
Obrigado! Eu entendi depois de ler estas frases: "Para facilitar a transição 2.x para 3.x, a sintaxe literal b '...' foi portada para o Python 2.6, a fim de permitir a distinção de cadeias binárias (o que deveria bytes na versão 3.x) das seqüências de texto (que devem ser str na versão 3.x) .O prefixo b não faz nada na versão 2.x, mas informa ao script 2to3 para não convertê-lo em uma seqüência de caracteres Unicode na versão 3.x. "
tommy.carstensen
4
O 'A' == b'A' --> Falsecheque realmente deixa claro. O resto é excelente, mas até aquele momento eu não havia entendido direito que uma sequência de bytes não
Curinga
12
'שלום עולם' == 'hello world'
Eli
12
Isso é muito mais claro do que a resposta aceita, que está apenas citando a documentação. A documentação para mim não fazia sentido, portanto, fornecer um contexto adicional na documentação é impressionante. Obrigado!
rayryeng
2
b "alguma string" .decode ( 'UTF-8'), eu acredito que essa é a linha muitos estão procurando
Marvin Thobejane
22

OB indica uma cadeia de bytes.

Bytes são os dados reais. Strings são uma abstração.

Se você tivesse um objeto de seqüência de caracteres múltiplos e utilizasse um único caractere, seria uma sequência e pode ter mais de 1 byte de tamanho, dependendo da codificação.

Se você digitar 1 byte com uma string de bytes, você obterá um único valor de 8 bits de 0 a 255 e pode não representar um caractere completo se esses caracteres devido à codificação forem> 1 byte.

TBH eu usaria strings, a menos que tivesse algum motivo específico de baixo nível para usar bytes.


fonte
16

Do lado do servidor, se enviarmos alguma resposta, ela será enviada na forma de tipo de byte e, portanto, aparecerá no cliente como b'Response from server'

Para se livrar de b'....' simplesmente use o código abaixo:

Arquivo do servidor:

stri="Response from server"    
c.send(stri.encode())

Arquivo do cliente:

print(s.recv(1024).decode())

então ele imprimirá Response from server

Nani Chintha
fonte
1
Não explica a pergunta que Jesse Webb fez!
Chandra Kanth
Eu estava dizendo que, sem usar métodos de codificação e decodificação, a saída da string será prefixada com b '', pois o python a toma como um tipo de byte em vez do tipo de string.Se você não deseja obter uma saída como b '... 'use o acima é isso. O que você não entendeu?
Nani Chintha
Na verdade, esta é exatamente a resposta ao título da pergunta que foi feita: P: "O que o b'x 'faz?" A: "Ele faz 'x'.encode ()" Isso é literalmente o que faz. O restante da pergunta queria saber muito mais do que isso, mas o título é respondido.
Michael Erickson
10

Aqui está um exemplo em que a ausência de blançaria uma TypeErrorexceção no Python 3.x

>>> f=open("new", "wb")
>>> f.write("Hello Python!")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' does not support the buffer interface

Adicionar um bprefixo resolveria o problema.

user3053230
fonte
9

Ele o transforma em um bytesliteral (oustr em 2.x) e é válido para 2.6+.

O rprefixo faz com que as barras invertidas para ser "uninterpreted" (não ignorada, ea diferença faz matéria).

Ignacio Vazquez-Abrams
fonte
Isso parece errado, de acordo com a documentação citada na resposta da aix; a b será ignorado em Python versão diferente 3.
Jesse Webb
2
Será um strno 2.x de qualquer maneira, portanto, pode-se dizer que é ignorado. A distinção importa quando você importa unicode_literalsdo __future__módulo.
Ignacio Vazquez-Abrams
6

Além do que os outros disseram, observe que um único caractere no unicode pode consistir em vários bytes .

A maneira como o unicode funciona é que ele pegou o formato ASCII antigo (código de 7 bits que se parece com 0xxx xxxx) e adicionou sequências de vários bytes em que todos os bytes começam com 1 (1xxx xxxx) para representar os caracteres além do ASCII, para que o Unicode fosse retrocedido. -compatível com ASCII.

>>> len('Öl')  # German word for 'oil' with 2 characters
2
>>> 'Öl'.encode('UTF-8')  # convert str to bytes 
b'\xc3\x96l'
>>> len('Öl'.encode('UTF-8'))  # 3 bytes encode 2 characters !
3
xjcl
fonte
2

Você pode usar JSON para convertê-lo em dicionário

import json
data = b'{"key":"value"}'
print(json.loads(data))

{"valor chave"}


FRASCO:

Este é um exemplo do balão. Execute isso na linha do terminal:

import requests
requests.post(url='http://localhost(example)/',json={'key':'value'})

No flask / routes.py

@app.route('/', methods=['POST'])
def api_script_add():
    print(request.data) # --> b'{"hi":"Hello"}'
    print(json.loads(request.data))
return json.loads(request.data)

{'valor chave'}

Karam Qusai
fonte