Шаг 190.
Python: сборник рецептов.
Модули и пакеты. Чтение файлов с данными внутри пакета

    На этом шаге мы рассмотрим использование функции 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.




Предыдущий шаг Содержание Следующий шаг