Eu estava tentando criar esse objeto de bytes no Python 3:
b'3\r\n'
então eu tentei o óbvio (para mim) e encontrei um comportamento estranho:
>>> bytes(3) + b'\r\n'
b'\x00\x00\x00\r\n'
Pelo visto:
>>> bytes(10)
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Não consegui ver nenhum ponteiro sobre por que a conversão de bytes funciona dessa maneira, lendo a documentação. No entanto, encontrei algumas mensagens surpresas neste problema do Python sobre como adicionar format
bytes (consulte também a formatação do Python 3 bytes ):
http://bugs.python.org/issue3982
Isso interage ainda mais mal com esquisitices como bytes (int) retornando zeros agora
e:
Seria muito mais conveniente para mim se bytes (int) retornassem a ASCIIfication desse int; mas, honestamente, até um erro seria melhor que esse comportamento. (Se eu quisesse esse comportamento - o que nunca tive - prefiro que seja um método de classe, invocado como "bytes.zeroes (n)").
Alguém pode me explicar de onde vem esse comportamento?
fonte
3 .to_bytes
Respostas:
Foi assim que foi projetado - e faz sentido, porque geralmente você poderia chamar
bytes
um iterável em vez de um único número inteiro:Os documentos afirmam isso , bem como a documentação para
bytes
:fonte
bytes
é apenas um apelido parastr
, o que significa quebytes([3])
você fornece'[3]'
.bytes([n])
só funciona para int n de 0 a 255. Para qualquer outra coisa, ele geraValueError
.bytes([3])
ainda é diferente do que o OP queria - ou seja, o valor de byte usado para codificar o dígito "3" em ASCII, ou seja.bytes([51])
, o que éb'3'
nãob'\x03'
.bytes(500)
cria uma bytestring com len == 500. Ele não cria uma bytestring que codifica o número inteiro 500. E eu concordo que issobytes([500])
não pode funcionar, e é por isso que essa é a resposta errada também. Provavelmente a resposta certa éint.to_bytes()
para versões> = 3.1.Do python 3.2 você pode fazer
https://docs.python.org/3/library/stdtypes.html#int.to_bytes
Por conseguinte
x == int_from_bytes(int_to_bytes(x))
,. Observe que essa codificação funciona apenas para números inteiros não assinados (não negativos).fonte
b"3"
de3
, como a questão pede. (Ele vai darb"\x03"
.)Você pode usar o pacote da estrutura :
O ">" é a ordem dos bytes (big endian) e o "I" é o caractere de formato . Portanto, você pode ser específico se desejar fazer outra coisa:
Isso funciona da mesma maneira no python 2 e no python 3 .
Nota: a operação inversa (bytes em int) pode ser feita com a descompactação .
fonte
I
,H
, eB
trabalho até2**k - 1
onde k é de 32, 16, e 8, respectivamente. Para insumos maiores, eles aumentamstruct.error
.b'3\r\n'
, ou seja, um byte-string contendo o caractere ASCII "3" não o caráter ASCII "\ x03"\x03
e a solução, se você quiser,b'3'
é trivial. A razão citada pela ABB é muito mais plausível ... ou pelo menos compreensível.bytes([x])
e(x).to_bytes()
no Python 3.5. Isso foi inesperado.O Python 3.5+ apresenta% -interpolation (
printf
formatação de estilo) para bytes :Consulte PEP 0461 - Adicionando% de formatação a bytes e bytearray .
Nas versões anteriores, você poderia usar
str
e.encode('ascii')
o resultado:Nota: É diferente do que
int.to_bytes
produz :fonte
A documentação diz:
A sequência:
É o caractere '3' (decimal 51) o caractere '\ r' (13) e '\ n' (10).
Portanto, a maneira como a trataria como tal, por exemplo:
Testado no IPython 1.1.0 e Python 3.2.3
fonte
bytes(str(n), 'ascii') + b'\r\n'
oustr(n).encode('ascii') + b'\r\n'
. Obrigado! :)"{}\r\n".format(n).encode()
eu não acho que haja qualquer dano feito usando a codificação UTF-8 padrãoA ASCIIfication de 3
"\x33"
não é"\x03"
!É para isso que o python faz,
str(3)
mas seria totalmente errado para bytes, pois eles devem ser considerados matrizes de dados binários e não devem ser abusados como strings.A maneira mais fácil de conseguir o que você quer é
bytes((3,))
, o que é melhor do quebytes([3])
porque a inicialização de uma lista é muito mais cara, portanto, nunca use listas quando puder usar tuplas. Você pode converter números inteiros maiores usandoint.to_bytes(3, "little")
.A inicialização de bytes com um determinado comprimento faz sentido e é a mais útil, pois eles costumam ser usados para criar algum tipo de buffer para o qual você precisa de alguma memória de determinado tamanho alocado. Costumo usar isso ao inicializar matrizes ou expandir algum arquivo escrevendo zeros nele.
fonte
b'3'
isb'\x33'
, notb'\x32'
. (b)(3)
não é uma tupla - você precisa adicionar uma vírgula. (c) O cenário de inicializar uma sequência com zeros não se aplica aosbytes
objetos, pois eles são imutáveis (embora faça sentido parabytearray
s).bytes
ebytearray
, acho que é principalmente uma questão de consistência. Mas também é útil se você deseja inserir alguns zeros em um buffer ou arquivo; nesse caso, ele é usado apenas como fonte de dados.int
(incluindo Python2long
) pode ser convertido para abytes
seguinte função:A conversão reversa pode ser feita por outra:
Ambas as funções funcionam no Python2 e Python3.
fonte
Eu estava curioso sobre o desempenho de vários métodos para um único int no intervalo
[0, 255]
, então decidi fazer alguns testes de temporização.Com base nos horários abaixo, e da tendência geral observei de tentar muitos valores e configurações diferentes,
struct.pack
parece ser o mais rápido, seguido porint.to_bytes
,bytes
e comstr.encode
(sem surpresa), sendo o mais lento. Note-se que os resultados mostram um pouco mais variação do que é representado, eint.to_bytes
ebytes
por vezes ligado a velocidade escalão durante os testes, masstruct.pack
é claramente o mais rápido.Resultados no CPython 3.7 no Windows:
Módulo de teste (nomeado
int_to_byte.py
):fonte
[0, 255]
. Presumo que por "indicador errado", você quer dizer que minhas medidas não foram gerais o suficiente para atender à maioria das situações? Ou minha metodologia de medição era ruim? Nesse último caso, eu estaria interessado em ouvir o que você tem a dizer, mas se o primeiro, nunca afirmei que minhas medidas fossem genéricas para todos os casos de uso. Para minha situação (talvez de nicho), estou lidando apenas com ints no intervalo[0, 255]
, e esse é o público que pretendi abordar com esta resposta. Minha resposta não estava clara? I pode editá-lo para maior clareza ...bytes((i,))
vez debytes([i])
porque a lista é mais complexa, use mais memória e demore muito para inicializar. Neste caso, por nada.Embora a resposta anterior do brunsgaard seja uma codificação eficiente, ela funciona apenas para números inteiros não assinados. Este baseia-se em trabalhar para números inteiros assinados e não assinados.
Para o codificador,
(i + ((i * signed) < 0)).bit_length()
é usado em vez de apenasi.bit_length()
porque o último leva a uma codificação ineficiente de -128, -32768 etc.Crédito: CervEd por corrigir uma pequena ineficiência.
fonte
int_to_bytes(-128, signed=True) == (-128).to_bytes(1, byteorder="big", signed=True)
éFalse
-128
,-32768
etc.(i+(signed*i<0)).bit_length()
O comportamento vem do fato de que no Python anterior à versão 3
bytes
era apenas um alias parastr
. No Python3.xbytes
existe uma versão imutável dobytearray
tipo + completamente novo, não compatível com versões anteriores.fonte
Dos bytes docs :
Em seguida, de bytearray docs :
Observe que isso difere do comportamento 2.x (onde x> = 6), onde
bytes
é simplesmentestr
:PEP 3112 :
fonte
Algumas respostas não funcionam com números grandes.
Converta inteiro para a representação hexadecimal e, em seguida, converta-o em bytes:
Resultado:
fonte
int.to_bytes
funciona com qualquer número inteiro.Se a questão é como converter um número inteiro em si (não sua string equivalente) em bytes, acho que a resposta robusta é:
Mais informações sobre esses métodos aqui:
fonte