На этом шаге мы рассмотрим использование функции pkgutil.get_data().
Ваш пакет включает файл с данными, который должен прочесть ваш код. Вам нужно обеспечить максимальную переносимость.
Предположим, что у вас есть пакет с такой организацией файлов:
mypackage/
__init__.py
somedata.dat
spam.py
Теперь предположим, что файл spam.py хочет прочитать содержимое файла somedata.dat. Чтобы это сделать, используйте такой код:
# spam.py import pkgutil data = pkgutil.get_data(__package__, 'somedata.dat')
Получившаяся переменная data будет байтовой строкой с необработанным содержимым файла.
Чтобы прочесть файл с данными, вы можете написать код, который использует встроенные функции ввода-вывода, такие как open(). Однако этот подход порождает несколько проблем.
Во-первых, пакет практически не контролирует текущий рабочий каталог интерпретатора. Поэтому любые операции ввода-вывода должны быть прописаны с использованием абсолютных имен файлов. Поскольку каждый модуль включает переменную __file__, содержащую полный путь, определить местоположение не невозможно, но это грязный код.
Во-вторых, пакеты часто инсталлируются как файлы .zip или .egg, которые не сохраняют файлы так же, как обычные каталоги файловой системы. Поэтому если вы попробуете использовать open() на находящемся в архиве файле с данными, это не сработает.
Функция pkgutil.get_data() - это высокоуровневый инструмент для получения файла с данными, независимо от того, где или как установлен пакет. Она "просто работает" и возвращает содержимое файла в форме байтовой строки.
Первый аргумент get_data() - это строка, которая содержит имя пакета. Вы можете либо предоставить ее напрямую, либо использовать специальную переменную, такую как __package__. Второй аргумент - это относительное имя файла внутри пакета. При необходимости вы можете переходить по каталогам, используя стандартные пути Unix, - до тех пор, пока конечный каталог все еще расположен внутри пакета.
На следующем шаге мы рассмотрим добавление каталогов в sys.path.