Baytları Python 3'te onaltılık bir dizeye dönüştürmenin doğru yolu nedir?


236

Baytları Python 3'te onaltılık bir dizeye dönüştürmenin doğru yolu nedir?

Bir bytes.hexyöntemin, bytes.decodekodeklerin iddialarını görüyorum ve boşuna olmadan en az şaşkınlığın diğer olası işlevlerini denedim . Baytlarımı onaltılık olarak istiyorum!


"boşuna"? Hangi spesifik sorunları veya hataları alıyorsunuz? Lütfen kodu ve hataları gösterin.
S.Lott

Yanıtlar:



95

binasciiModülü kullanın :

>>> import binascii
>>> binascii.hexlify('foo'.encode('utf8'))
b'666f6f'
>>> binascii.unhexlify(_).decode('utf8')
'foo'

Şu cevaba bakın: Python 3.1.1 dizesi onaltılı


8
Bu iyi. Mind boggling, bytes.fromhex (hex_str) kullanarak hex'i byte'a dönüştürebilmenizdir, ancak bytes.tohex () kullanarak byte'ları hex'e dönüştüremezsiniz - bunun mantıklı tarafı nedir?
nagylzs

1
Bayt ve hex arasındaki ilişki ya bir özellik değildir sanırım (bu neden fromhex var cevap vermez). Bu sadece bir gözetim değil, üzerinde tartışılan bir şey gibi görünüyor: bugs.python.org/issue3532#msg70950 . S: Bu görevi gerçekleştirmek için bayt nesnesinin tohex yöntemine sahip olmak acı verir mi? A: IMO, evet, olur. Kodu karmaşıklaştırır ve odağı veri dönüştürmeye doğru yaklaşımdan (yani, işlevler değil, yöntemler) uzaklaştırır.
Mu Mind

3
Bu gerçekten soruyu cevaplıyor mu? Bir hex strdeğil, bir bytes. OP cevabından memnun göründüğünü biliyorum ama bu cevabı .decode("ascii")bir “string” e dönüştürmek için de dahil etmek için daha iyi olmayacak
RubenLaguna

3
Birçok insanın bu soru / cevap üzerine çıktı almanın bir yolunu aradığını düşünüyordum bytes. Eğer print(b'666f6f')sen almak bçıktıda içinde. Eğer öyleyse .decode("ascii")yapmazsın. Sadece bytes(ascii bir dize değil, 128'den büyük öğelerle gerçek ikili) olanların çıktı almak istediklerini düşünmek.
RubenLaguna

5
@nagylzs: .hex()Python 3.5+ ' da yöntem var
jfs

43

Python, alıntılanan yazdırılabilir (7 bit ascii'ye sığar), base64 (alfanümeriklere uyar), altıgen kaçan, gzip ve bz2 sıkıştırma gibi uygun dönüşümleri gerçekleştiren bayt-bayt standart kodeklere sahiptir. Python 2'de şunları yapabilirsiniz:

b'foo'.encode('hex')

Python 3'te, str.encode/ bytes.decodekesinlikle bayt <-> str dönüşümleri içindir. Bunun yerine, Python 2 ve Python 3 ( tersi için s / encode / decode / g ) üzerinde çalışan bunu yapabilirsiniz:

import codecs
codecs.getencoder('hex')(b'foo')[0]

Python 3.4 ile başlayarak, daha az garip bir seçenek var:

codecs.encode(b'foo', 'hex')

Bu çeşitli kodeklere kendi modüllerinde de erişilebilir (base64, zlib, bz2, uu, quopri, binascii); API daha az tutarlıdır, ancak sıkıştırma kodekleri için daha fazla kontrol sunar.


1
python 3.3 kullanarak:LookupError: unknown encoding: hex
Janus Troelsen

@ JanusTroelsen: 'hex_codec'i deneyin . Veya sadece binascii.hexlify(b'foo')doğrudan kullanın
jfs

7
import codecs
codecs.getencoder('hex_codec')(b'foo')[0]

Python 3.3'te çalışır (yani "hex" yerine "hex_codec").


Belki de ilginçtir, Python 3.4'te "hex" veya "hex_codec" iyi çalışır.
Stephen Paulger

6

Yöntem binascii.hexlify()dönüştürür bytesa bytesASCII altıgen dizisi temsil eder. Bu, girişteki her baytın iki ascii karakterine dönüştürüleceği anlamına gelir. Eğer gerçek bir sonuç stristiyorsanız o zaman .decode("ascii")sonuç yapabilirsiniz .

Bunu gösteren bir pasaj ekledim.

import binascii

with open("addressbook.bin", "rb") as f: # or any binary file like '/bin/ls'
    in_bytes = f.read()
    print(in_bytes) # b'\n\x16\n\x04'
    hex_bytes = binascii.hexlify(in_bytes) 
    print(hex_bytes) # b'0a160a04' which is twice as long as in_bytes
    hex_str = hex_bytes.decode("ascii")
    print(hex_str) # 0a160a04

onaltılık dize gelen "0a160a04"geri dönebilirsiniz için bytesbirlikte binascii.unhexlify("0a160a04")hangi geri verirb'\n\x16\n\x04'


3

Tamam, sadece Python 3 veriyorsan aşağıdaki cevabı biraz ötesinde kapsam, ama bu soru ilk Google Python sürümünü belirtmek olmasa bile isabet, bu yüzden burada bir yol olduğunu Python 2 hem çalışır ve Python 3 .

Ben de bayt strtürüne dönüştürme sorusunu yorumluyorum : yani Python 2'de bayt-y ve Python 3'te Unicode-y.

Bu göz önüne alındığında, bildiğim en iyi yaklaşım:

import six

bytes_to_hex_str = lambda b: ' '.join('%02x' % i for i in six.iterbytes(b))

Python 2'de unicode_literalsgeleceği etkinleştirmediğiniz varsayılarak, aşağıdaki iddia Python 2 veya Python 3 için geçerli olacaktır :

assert bytes_to_hex_str(b'jkl') == '6a 6b 6c'

(Veya ''.join()baytlar arasındaki boşluğu atlamak için kullanabilirsiniz .)


3

%x02onaltılık bir değeri biçimlendiren ve çıktı alan biçim belirleyici kullanılabilir . Örneğin:

>>> foo = b"tC\xfc}\x05i\x8d\x86\x05\xa5\xb4\xd3]Vd\x9cZ\x92~'6"
>>> res = ""
>>> for b in foo:
...     res += "%02x" % b
... 
>>> print(res)
7443fc7d05698d8605a5b4d35d56649c5a927e2736

Bana göre, bu en iyi yanıttır çünkü her Python sürümü ile çalışır ve herhangi bir içe aktarmaya gerek yoktur. Yine de, büyük harflerle altıgen dizeleri göstermeliyimres.upper()
Bruno L.


0

B '\ x61' ifadesini 97 veya '0x61' değerine dönüştürmek istiyorsanız şunu deneyebilirsiniz:

[python3.5]
>>>from struct import *
>>>temp=unpack('B',b'\x61')[0] ## convert bytes to unsigned int
97
>>>hex(temp) ##convert int to string which is hexadecimal expression
'0x61'

Referans: https://docs.python.org/3.5/library/struct.html


Her nasılsa esp32 ile yardımcı olur
Tejas Tank
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.