Python записывает длинное целое как двоичное значение в файл

Я пытался взять длинный int (m39 prime) и сохранить его как двоичный файл. Когда я пытаюсь записать значение bin в файл, оно записывается в виде строки.

>>> m39 = bin(2**13466917-1)
>>> open('m39', 'wb').write(m39) 
madsc13ntist@jaberwock:~/Desktop$ xxd m39 | head
0000000: 3062 3131 3131 3131 3131 3131 3131 3131  0b11111111111111
0000010: 3131 3131 3131 3131 3131 3131 3131 3131  1111111111111111
0000020: 3131 3131 3131 3131 3131 3131 3131 3131  1111111111111111
0000030: 3131 3131 3131 3131 3131 3131 3131 3131  1111111111111111
0000040: 3131 3131 3131 3131 3131 3131 3131 3131  1111111111111111
0000050: 3131 3131 3131 3131 3131 3131 3131 3131  1111111111111111
0000060: 3131 3131 3131 3131 3131 3131 3131 3131  1111111111111111
0000070: 3131 3131 3131 3131 3131 3131 3131 3131  1111111111111111
0000080: 3131 3131 3131 3131 3131 3131 3131 3131  1111111111111111

Я почти уверен, что на этот вопрос есть смехотворно простой ответ, но мне не удалось преобразовать m39 в байтовый массив или буфер для записи. Должен ли я использовать io или memoryview и т.д.

Заранее большое спасибо за любую помощь, которую кто-либо может предоставить. :)

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

РЕДАКТИРОВАТЬ: я пытаюсь сохранить значение в виде двоичного файла, который будет занимать гораздо меньше места на диске/памяти. Я понимаю, что тип bin — это строка в python, но я пытаюсь написать \x11\x11\x11\x11 not \x31\x31\x31\x31. Мое намерение состоит не в том, чтобы напечатать строковое представление значения, а в том, чтобы эффективно сохранить его для последующего использования/манипулирования.


person MadSc13ntist    schedule 24.03.2013    source источник


Ответы (2)


Вы должны либо использовать модуль struct, либо массив в зависимости от структуры данных (т.е. для массива однородных значений массив будет проще/быстрее).

person lqc    schedule 24.03.2013

Модуль Python pickle довольно эффективен. Представление всего на 8 байтов длиннее, чем может быть сохранено необработанное двоичное значение. Это работает в Python 2.X или 3.X:

import pickle
m39 = 2**13466917-1
with open('m39.dat','wb') as f:
    pickle.dump(m39,f,pickle.HIGHEST_PROTOCOL)

Получившийся шестнадцатеричный дамп (1 683 373 байта):

 80 03 8B A5 AF 19 00 FF FF FF ... FF FF FF 1F 2E

Чтобы прочитать обратно:

import pickle
with open('m39.dat','rb') as f:
   m39 = pickle.load(f)

Python 3 также имеет методы to_bytes и from_bytes для целых чисел, но требует немного больше работы, так как необходимо вычислить длину целого числа в байтах.

import math
m39 = 2**13466917-1
s = m39.to_bytes(math.ceil(m39.bit_length()/8),'little')
with open('m39.dat','wb') as f:
    f.write(s)

Получившийся шестнадцатеричный дамп (1 683 365 байт):

 FF FF FF FF FF FF FF FF FF FF ... FF FF FF FF 1F

Чтобы прочитать обратно:

with open('m39.dat','rb') as f:
    data = f.read()
m39 = int.from_bytes(data,'little')

Очевидно, что там есть шаблон, и было бы более эффективно вместо этого просто хранить показатель степени простого числа.

person Mark Tolonen    schedule 24.03.2013