Py2exe: встроить статические файлы в файл exe и получить к ним доступ

Я нашел решение для добавления файлов в library.zip через: Расширить py2exe для копирования файлов в zip файл, где pkg_resources может их загрузить.

Я могу получить доступ к моему файлу, когда library.zip не включает exe.

Я добавляю файл: text.txt в каталог: foo/media в library.zip. И я использую этот код:

import pkg_resources
import zipfile
from cStringIO import StringIO

my_data = pkg_resources.resource_string(__name__,"library.zip")

filezip = StringIO(my_data)
zip = zipfile.ZipFile(filezip)
data = zip.read("foo/media/text.txt")

Я пытаюсь использовать pkg_resources, но я думаю, что я ничего не понимаю, потому что я могу открыть непосредственно "library.zip".

Мой вопрос в том, как я могу это сделать, когда library.zip встроен в exe?

С наилучшими пожеланиями

Жан-Мишель

Ответ 1

Я объединил достаточно аккуратное решение, но оно не использует pkg_resources.

Мне нужно распространять инструменты производительности как автономные EXE, то есть все, входящие в один .exe файл. Мне также нужно отправлять уведомления, когда эти инструменты используются, что я делаю с помощью API ведения журнала, используя конфигурацию на основе файлов. Я удалил файл logging.cfg, чтобы сделать его более сложным для эффективного отключения этих уведомлений, то есть путем удаления свободного файла... который, вероятно, повредил бы приложение в любом случае.

Итак, следующие интересные биты из моего setup.py:

LOGGING_CFG = open('main/resources/logging.cfg').read()

setup(
    name='productivity-tool',
    ...

    # py2exe extras
    console=[{'script': productivity_tool.__file__.replace('.pyc', '.py'),
              'other_resources': [(u'LOGGINGCFG', 1, LOGGING_CFG)]}],
    zipfile=None,
    options={'py2exe': {'bundle_files': 1, 'dll_excludes': ['w9xpopen.exe']}},
)

Затем в стартовом коде для performance_tool.py:

from win32api import LoadResource
from StringIO import StringIO
from logging.config import fileConfig
...

if __name__ == '__main__':
    if is_exe():
        logging_cfg = StringIO(LoadResource(0, u'LOGGINGCFG', 1))
    else:
        logging_cfg = 'main/resources/logging.cfg'
    fileConfig(logging_cfg)
    ...

Работает с удовольствием!!!

Ответ 2

Спасибо, но я нашел решение

my_data = pkg_resources.resource_stream("__main__",sys.executable) # get lib.zip file
zip = zipfile.ZipFile(my_data)
data = zip.read("foo/media/doc.pdf") # get my data on lib.zip
file = open(output_name, 'wb')
file.write(data) # write it on a file
file.close()

С наилучшими пожеланиями

Ответ 3

Вы не должны использовать pkg_resources для извлечения файла library.zip. Вы должны использовать его для извлечения добавленного ресурса.

Предположим, что у вас есть следующая структура проекта:

setup.py
foo/
    __init__.py
    bar.py
    media/
        image.jpg

Для доступа к image.jpg:

вы должны использовать resource_string (или, желательно, resource_stream)
img = pkg_resources.resource_string(__name__, 'media/image.jpg')

Это должно "просто работать". По крайней мере, это произошло, когда я связал свои медиафайлы в EXE. (Извините, с тех пор я покинул компанию, где я использовал py2exe, поэтому нет рабочего примера для рисования.)

Вы также можете попробовать использовать pkg_resources.resource_filename(), но я не думаю, что это работает под py2exe.