Альтернатива использованию __file__ найти бинарную папку в моем пакете python - PullRequest
0 голосов
/ 31 января 2020

Я опубликовал библиотеку для PyPI ('nmrsim'), которая имеет следующую структуру (отредактированную для включения только соответствующих файлов / папок):

nmrsim
├── nmrsim
│   ├── __init__.py
│   ├── bin
│   │   ├── T1.npz
│   │   ⋮
│   │   └── T11.npz
│   | 
│   └── qm.py
│   
└── tests
    └── test_qm.py

Каталог bin содержит двоичные файлы (разреженные матрицы) частичных решений) для более быстрых расчетов. Чтобы qm.py обнаружил каталог bin независимо от того, где он установлен и откуда вызывается (например, основное приложение конечного пользователя, набор тестов модуля tests/test_qm.py, IDE ...), используются ссылки на __file__, например, в qm.py:

def _tm_cache(nspins):
    filename = f'T{nspins}.npz'
    bin_dir = os.path.join(os.path.dirname(__file__), 'bin')
    path = os.path.join(bin_dir, filename)
    try:
        T_sparse = sparse.load_npz(path)
        return T_sparse
    except FileNotFoundError:
        <work around missing file>

Библиотека может быть успешно установлена ​​с помощью pip и использована на разных платформах. Однако использование PyInstaller для создания замороженного приложения из 1 файла завершается неудачно, поскольку каталог bin не включен. Просматривая документацию по PyInstaller и PyOxidizer (возможное предупреждение), кажется, что использование файла проблематично c для "зависания" python приложений.

Как я могу рефакторинг такого кода, чтобы избежать использования __file__?

1 Ответ

0 голосов
/ 02 февраля 2020

Я нашел рабочее решение:

  1. Добавьте __init__.py в папку bin.
  2. Импортируйте папку bin как модуль, например, qm.py будет иметь оператор import nmrsim.bin.
  3. Используйте importlib.resources.path для создания объекта диспетчера контекста:
filename = f'T{nspins}.npz'
path_context = resources.path(nmrsim.bin, filename)
Используйте менеджер контекста с блоком «with ... as» для получения пути:
with path_context as p:
    path = p
...