Bagaimana saya bisa mengubah string byte menjadi int di python?
Katakan seperti ini: 'y\xcc\xa6\xbb'
Saya datang dengan cara pintar / bodoh untuk melakukannya:
sum(ord(c) << (i * 8) for i, c in enumerate('y\xcc\xa6\xbb'[::-1]))
Saya tahu harus ada sesuatu bawaan atau di perpustakaan standar yang melakukan ini lebih sederhana ...
Ini berbeda dengan mengonversi string angka hex yang dapat Anda gunakan int (xxx, 16), tetapi saya ingin mengonversi string nilai byte aktual.
MEMPERBARUI:
Saya agak suka jawaban James sedikit lebih baik karena tidak perlu mengimpor modul lain, tetapi metode Greg lebih cepat:
>>> from timeit import Timer
>>> Timer('struct.unpack("<L", "y\xcc\xa6\xbb")[0]', 'import struct').timeit()
0.36242198944091797
>>> Timer("int('y\xcc\xa6\xbb'.encode('hex'), 16)").timeit()
1.1432669162750244
Metode hacky saya:
>>> Timer("sum(ord(c) << (i * 8) for i, c in enumerate('y\xcc\xa6\xbb'[::-1]))").timeit()
2.8819329738616943
PEMBARUAN LEBIH LANJUT:
Seseorang bertanya dalam komentar apa masalah dengan mengimpor modul lain. Nah, mengimpor modul belum tentu murah, lihat:
>>> Timer("""import struct\nstruct.unpack(">L", "y\xcc\xa6\xbb")[0]""").timeit()
0.98822188377380371
Termasuk biaya mengimpor modul meniadakan hampir semua keuntungan yang dimiliki metode ini. Saya percaya bahwa ini hanya akan mencakup biaya impor sekali untuk seluruh proses benchmark; lihat apa yang terjadi ketika saya memaksanya memuat ulang setiap kali:
>>> Timer("""reload(struct)\nstruct.unpack(">L", "y\xcc\xa6\xbb")[0]""", 'import struct').timeit()
68.474128007888794
Tak perlu dikatakan, jika Anda melakukan banyak eksekusi metode ini per satu impor daripada ini menjadi kurang proporsional masalah. Ini juga mungkin biaya i / o daripada cpu sehingga mungkin tergantung pada kapasitas dan karakteristik beban mesin tertentu.
int.from_bytes
) tampilstruct.unpack
di komputer saya. Selanjutnya menjadi imo yang lebih mudah dibaca.Jawaban:
Anda juga dapat menggunakan modul struct untuk melakukan ini:
sumber
Dalam Python 3.2 dan yang lebih baru, gunakan
atau
sesuai dengan endianness byte-string Anda.
Ini juga berfungsi untuk bytestring-integer dengan panjang sewenang-wenang, dan untuk dua's melengkapi integer yang ditandatangani dengan menentukan
signed=True
. Lihat dokumen untukfrom_bytes
.sumber
os.urandom(4)
byte ** 1,4 µs ** (struct) vs ** 2.3 µs ** (int.from_bytes) pada cpu saya. python 3.5.2Seperti kata Greg, Anda dapat menggunakan struct jika Anda berurusan dengan nilai-nilai biner, tetapi jika Anda hanya memiliki "nomor hex" tetapi dalam format byte Anda mungkin ingin mengonversinya seperti:
... ini sama dengan:
... kecuali itu akan bekerja untuk sejumlah byte.
sumber
int(''.join(reversed(s)).encode('hex'), 16)
Saya menggunakan fungsi berikut untuk mengkonversi data antara int, hex, dan byte.
Sumber: http://opentechnotes.blogspot.com.au/2014/04/convert-values-to-from-integer-hex.html
sumber
Peringatan: di atas sangat spesifik platform. Baik specifier "I" dan endianness dari konversi string-> int tergantung pada implementasi Python Anda. Tetapi jika Anda ingin mengonversi banyak bilangan bulat / string sekaligus, maka modul array melakukannya dengan cepat.
sumber
Di Python 2.x, Anda bisa menggunakan penentu format
<B
untuk byte yang tidak ditandatangani, dan<b
untuk byte yang ditandatangani denganstruct.unpack
/struct.pack
.Misalnya:
Biarkan
x
='\xff\x10\x11'
Dan:
Itu
*
wajib!Lihat https://docs.python.org/2/library/struct.html#format-characters untuk daftar penentu format.
sumber
Tes 1: terbalik:
Tes 2: Jumlah byte> 8:
Uji 3: Bertambah satu:
Tes 4: Tambahkan satu byte, katakan 'A':
Tes 5: Bagilah dengan 256:
Hasil sama dengan hasil Tes 4, seperti yang diharapkan.
sumber
Saya berjuang untuk menemukan solusi untuk urutan byte panjang sewenang-wenang yang akan bekerja di bawah Python 2.x. Akhirnya saya menulis yang ini, sedikit hacky karena melakukan konversi string, tetapi berhasil.
Fungsi untuk Python 2.x, panjang sewenang-wenang
Fungsi ini memiliki dua persyaratan:
Input
data
harus berupa abytearray
. Anda dapat memanggil fungsi seperti ini:Data harus big-endian. Jika Anda memiliki nilai little-endian, Anda harus membalikkannya terlebih dahulu:
Tentu saja, ini harus digunakan hanya jika panjang sewenang-wenang diperlukan. Kalau tidak, tetap dengan cara yang lebih standar (misalnya
struct
).sumber
int.from_bytes adalah solusi terbaik jika Anda berada di versi> = 3.2. Solusi "struct.unpack" memerlukan string sehingga tidak akan berlaku untuk array byte. Ini solusi lain:
hex (bytes2int ([0x87, 0x65, 0x43, 0x21])) mengembalikan '0x87654321'.
Ini menangani endianness besar dan kecil dan mudah dimodifikasi untuk 8 byte
sumber
Seperti disebutkan di atas menggunakan
unpack
fungsi struct adalah cara yang baik. Jika Anda ingin mengimplementasikan fungsi Anda sendiri ada solusi lain:sumber
Dalam python 3 Anda dapat dengan mudah mengkonversi string byte menjadi daftar integer (0..255) oleh
sumber
Metode yang sopan cepat menggunakan array.array saya telah menggunakan untuk beberapa waktu:
variabel yang telah ditentukan:
ke int: (baca)
dari int: (tulis)
Mungkin ini bisa lebih cepat.
EDIT:
Untuk beberapa angka, inilah tes kinerja (Anaconda 2.3.0) yang menunjukkan rata-rata stabil saat dibaca dibandingkan dengan
reduce()
:Ini adalah tes kinerja mentah, sehingga endian pow-flip ditinggalkan.
The
shift
fungsi yang ditampilkan berlaku operasi pergeseran-oring sama dengan untuk loop, danarr
hanyaarray.array('B',[0,0,255,0])
karena memiliki performa tercepat berulang sebelahdict
.Saya mungkin juga harus mencatat efisiensi diukur dengan akurasi dengan waktu rata-rata.
sumber