Если py2exe включает мои файлы данных (например, include_package_data)

У меня есть приложение Python, которое включает файлы данных, отличные от Python, в некоторые из его подпакетов. Я использовал опцию include_package_data в своем setup.py для автоматического включения всех этих файлов при создании дистрибутивов. Это работает хорошо.

Теперь я начинаю использовать py2exe. Я ожидал, что он увидит, что у меня есть include_package_data=True, и включит все файлы. Но это не так. Он помещает только мои файлы Python в library.zip, поэтому мое приложение не работает.

Как заставить py2exe включать мои файлы данных?


person Ram Rachum    schedule 30.04.2010    source источник


Ответы (4)


В итоге я решил это, предоставив py2exe опцию skip_archive=True. Это привело к тому, что файлы Python были помещены не в library.zip, а просто как обычные файлы. Затем я использовал data_files, чтобы поместить файлы данных прямо в пакеты Python.

person Ram Rachum    schedule 30.04.2010

include_package_data — это опция setuptools, а не distutils. В классических distutils вы должны сами указать расположение файлов данных, используя директиву data_files = []. py2exe то же самое. Если у вас много файлов, вы можете использовать glob или os.walk для их извлечения. См., например, дополнительные изменения (добавления файла данных), необходимые для setup.py, чтобы сделать модуль, такой как MatPlotLib, работает с py2exe.

Существует также список рассылки обсуждение, актуально.

person ire_and_curses    schedule 30.04.2010
comment
Насколько я помню, есть проблема с data_files: то, как вы указываете путь, по которому он должен установить файлы данных, не зависит от того, где находится ваш пакет. Например, если вы укажете '', он скопирует файлы данных в c:\Python26\ , что плохо. Так что да, вы можете указать 'Lib\site-packages\whatever', но тогда все сломается, если пользователь установил пакет в какую-то другую папку. Есть ли решение? - person Ram Rachum; 01.05.2010
comment
Сейчас я попробовал это, и проблема отличается от той, которую я помнил. (Тогда я просто устанавливал с setup.py, а теперь мы делаем py2exe, так что все по-другому.) Что происходит, так это то, что файлы помещаются в каталог dist рядом с .exe. Это плохо, потому что они должны быть внутри library.zip на их естественном месте внутри различных пакетов Python. Как я могу заставить их быть помещенными в library.zip? - person Ram Rachum; 01.05.2010

Вот что я использую, чтобы заставить py2exe собрать все мои файлы в .zip. Обратите внимание, что для доступа к вашим файлам данных вам необходимо открыть zip-файл. py2exe не будет перенаправлять вызовы за вас.

setup(windows=[target],
      name="myappname",
      data_files = [('', ['data1.dat', 'data2.dat'])],
      options = {'py2exe': {
        "optimize": 2,
        "bundle_files": 2, # This tells py2exe to bundle everything
      }},
)

Полный список параметров py2exe находится здесь.

person Daniel Stutzbach    schedule 30.04.2010
comment
B-list парень ответил на мой вопрос! Я горжусь. Но в любом случае я бы не хотел помещать файлы данных в файл .exe, я бы хотел, чтобы они были в пакетах Python. - person Ram Rachum; 01.05.2010
comment
@cool-RR Я обновил свой ответ, указав настройки, чтобы упаковать все в .zip. - person Daniel Stutzbach; 01.05.2010
comment
Вау, не знал про вариант bundle_files, спасибо. Хотя мне начинает нравиться идея не иметь zip-файла, так что я думаю, что буду придерживаться этого. - person Ram Rachum; 01.05.2010
comment
Ваше решение не работает для меня. Файлы данных не включены в library.zip. - person Alex van Houten; 20.12.2011

Я смог сделать это, переопределив одну из функций py2exe, а затем просто вставив их в zip-файл, созданный py2exe.

Вот пример:

import py2exe
import zipfile

myFiles = [
    "C:/Users/Kade/Documents/ExampleFiles/example_1.doc",
    "C:/Users/Kade/Documents/ExampleFiles/example_2.dll",
    "C:/Users/Kade/Documents/ExampleFiles/example_3.obj",
    "C:/Users/Kade/Documents/ExampleFiles/example_4.H",
    ]

def better_copy_files(self, destdir):
    """Overriden so that things can be included in the library.zip."""

    #Run function as normal
    original_copy_files(self, destdir)

    #Get the zipfile's location
    if self.options.libname is not None:
        libpath = os.path.join(destdir, self.options.libname)

        #Re-open the zip file
        if self.options.compress:
            compression = zipfile.ZIP_DEFLATED
        else:
            compression = zipfile.ZIP_STORED
        arc = zipfile.ZipFile(libpath, "a", compression = compression)

        #Add your items to the zipfile
        for item in myFiles:
            if self.options.verbose:
                print("Copy File %s to %s" % (item, libpath))
            arc.write(item, os.path.basename(item))
        arc.close()

#Connect overrides
original_copy_files = py2exe.runtime.Runtime.copy_files
py2exe.runtime.Runtime.copy_files = better_copy_files

Я получил эту идею из здесь, но, к сожалению, py2exe изменил способ делай что-то смысл тогда. Я надеюсь, что это поможет кому-то.

person Kade    schedule 22.08.2017