Двоичные форматы

Архивы

В стандартной библиотеке Python есть модули для работы с .zipzipfile, для прочих открытых форматов архивов существует обертка к библиотеке libarchive[pip].

Работа с zip архивами через zipfile

.zip архив состоит из сжатых (одним из 4 алгоритмов) файлов, к каждому из которых можно обратиться зная его уникальное имя (включающее путь), это имя и используется при распаковке (при необходимости создаются соответствующие папки).

Чтение

import zipfile

zobj = zipfile.ZipFile('test.zip')

lns = obj.namelist()
# lns == ['data/test1.txt', 'data/test2.txt']

fobj = zobj.open('data/file.txt')
# Файл всегда открывается в режиме binary!
s = fobj.read() 
#s == b'Test zip file content'
fobj.close()
zobj.close()

Запись

Поддерживаются опции w — перезапись архива, a — дополнение архива (если архива нет, то он будет создан) и x— дополнение архива (если архива нет, то будет выброшено исключение).

import zipfile

zobj = zipfile.ZipFile('test.zip', 'a')
zobj.writestr('test.txt', b'Testing data', zipfile.ZIP_DEFLATED)
zobj.close()

Флаг zipfile.ZIP_DEFLATED необходим, иначе файл будет добавлен в архив без сжатия.

В архиве .zip нельзя создать пустую папку и нельзя сохранить атрибуты папки. Файл из архива .zip нельзя удалить, изменить или переименовать.

Кроме того zipfile позволяет извлекать файлы из архива (extract, extractall), и добавлять их в архив по имени файла (write). См. документацию.

Изображения

Обработка изображений дело ресурсоемкое, поэтому библиотеки Python для работы с картинками обычно имеют высокоуровневый интерфейс, под которым прячется начинка на C. Рассмотрим работу с картинками на примере библиотеки Pillow[pip].

Библиотека загружает и хранит изображение в памяти целиком в одном из поддерживаемых типов массивов. Вот некоторые популярные типы массивов:

Тип Байт на пиксель Описание
1 1 Монохромное изображение
L 1 В оттенках серого
RGB 3 Цветное изображение без прозрачности
RGBA 4 Цветное изображение c прозрачностью
HSV 3 Кодирование Тон-Яркость-Значение

Чтение

Поддерживаемых форматов очень много.

from PIL import Image

# Открытые файла
im = Image.open("test.png")
im.load() # Отложенное чтение

# Создание нового изображения
im = Image.new("RGB", (100,100))

# Создание изображения из массива
im = Image.frombytes("L", (100,100), data)

Рисование

from PIL import Image, ImageDraw, ImageFont

im = Image.open("test.png")

# Создание объекта для рисования
draw = ImageDraw.Draw(im)

# Рисование
draw.line((0, 0) + im.size, fill=128)
font = ImageFont.truetype("arial.ttf", 15)
draw.text((40,40),"Привет!",font=font)

# Размер изображения
s = im.size
# s == (100, 100)

Запись

from PIL import Image

im = Image.open("test.png")

# Преобразуем тип данных
mim = im.convert('L')

# Просмотр
mim.show()

# Получаем байты в соответствии с типом
bs = mim.tobytes()
# bs = b'&\x00\x00\x00\x00\x00\x00\x00\x00...

# Сохраняем файл
mim.save("test.bmp")

Если нужно получить закодированное в заданном формате (.bmp, .jpg) изображение, то методу save надо подложить io.BytesIO объект и указать формат через аргумент format.

Офисные документы

Офисные документы можно относительно просто читать и создавать с помощью этих библиотек.

Расширение Название Модуль
.docx MS Office 2007 Word python-docx[pip]
.xls MS Office 1997 Excel xlrd[pip], xlwt[pip]
.xlsx MS Office 2007 Excel openpyxl[pip]
.odt OpenDocument Text odfpy[pip]
.ods OpenDocument SpreadSheet odfpy[pip]
.pdf Portable Document Format reportlab[pip]
.svg Scalable Vector Graphics svgwrite[pip]

Однако схема «открыл → изменил → сохранил» может вызывать проблемы. В этих случаях лучше использовать API офисных пакетов.

Чтение электронных таблиц XLSX

from openpyxl import load_workbook

wb = load_workbook("sample.xlsx")
ws = wb.active # Выбор листа

print(ws['A1'].value)  # С использованием Excel нотации
print(ws.cell(1, 1).value) # По индексу сроки/столбца

for  row in ws.rows: # По всем строкам на листе
        print(row[0].value, row[1].value)

Запись электронных таблиц XLSX

from openpyxl import Workbook
wb = Workbook()
ws = wb.active  # Выбор листа

ws['A1'] = 42 # С использованием Excel нотации
ws.cell(1, 1, 42) # По индексу сроки/столбца

wb.save("sample.xlsx")

Чтение NetCDF4

from netCDF4 import Dataset

#https://www.unidata.ucar.edu/software/netcdf/examples/sresa1b_ncar_ccsm3-example.nc

ncdata = Dataset("sresa1b_ncar_ccsm3-example.nc", format="NETCDF4")

print(ncdata.variables.keys()) # Обзор всех переменных

# Основная переменная:
print(ncdata['ua'].shape) # (1, 17, 128, 256)

# Оси:
print(ncdata['plev'].shape) # (17,)
print(ncdata['lat'].shape)  # (128,)
print(ncdata['lon'].shape)  # (256,)

# Чтение данных:
plev = ncdata['plev'][:]
lat = ncdata['lat'][:]
lon = ncdata['lon'][:]
ua = ncdata['ua'][:]

#Конкретная точка
print(plev[1],lat[20],lon[20],ua[0,1,20,20])

Что еще нужно знать о работе с двоичными форматами

  • Структура произвольного двоичного формата обычно описывается в виде C-структур, поэтому читать такие файлы целесообразно с использованием cffi, ctypes или struct.
  • Иногда встречаются беззаголовочные бинарные файлы. Например результаты работы регистратора.
  • Формат некоторых двоичный файлов неизвествен и/или охраняется как объект авторского права.
  • В идеальном случае спецификация формата известна, в этом случае практически наверняка есть открытая библиотека для работы с такими файлами.
  • Некоторые форматы могут иметь собственные версии.
  • Могут возникать проблемы совместимости между различными версиями программ/библиотек для чтения и записи файлов.