Cx freeze linux python

cx_Freeze + virtualenv = баги и зигзаги

Установка cx_Freeze

Не подходит, потому что устанавливает cx_Freeze для Python2.

Попробуем через pip3:

Однако, как бы не так. На Убунте (другие ОС пока не пробовал) это вызывает следующую ошибку (прошу прощения за картинки. На момент написания статьи сделать текстовый копипаст оказалось затруднительно по причинам из серии «это долгая история»):

Порывшись по StackExchange, я понял, что без установки из исходников дело не обойдётся.

Скачал. Распаковал. Запустил:

Снова порылся по StackOverflow. Пришлось залезть в setup.py и заменить там строчку:

Попробовал запустить снова — и установилось! Ура!

На заметку

Собираем скрипт!

где main.py — имя основного (запускаемого) скрипта, а build — папка, куда пойдут исполняемый файл и библиотеки.

Следует учитывать, что в отличие от, скажем, компиляторов C++, cx_Freeze не отлавливает ошибки. Поэтому он может прекрасно всё собрать, но при запуске исполняемого файла посыпятся исключения, причём в довольно неразборчивом формате. Советую потестить код, пока он ещё питонический.

Думаю, что оптимизация кода для сборки в исполняемый файл — тема для отдельного обсуждения, ибо при сборке могут вылезти проблемы, которых при запуске скрипта через интерпретатор Python просто не было. Здесь расскажу об одной (слава богу, одной! больше просто не возникло) такой проблеме.

Мой скрипт обращается к внешним файлам с настройками. Но при запуске из исполняемого файла он почему-то стал воспринимать имя скрипта, как одну из папок на пути к файлу настроек. То есть, если собранный исполняемый файл под названием main находится в /tmp/001, а файл настроек — в /tmp/001/sett, то скрипт думал, что файл настроек на самом деле располагается в /tmp/001/main/sett. Что, естественно, бред. А если же запустить питоновый скрипт — этой проблемы нет.

Дело в том что я в начале своих программ зачастую впихиваю следующую строчку:

Эту переменную я потом использую при задании путей к файлам, которые всегда находятся в одном и том же месте относительно скрипта: файлы настроек, сохранения, токены, коды приложений, и т. д. Таким образом я гарантирую, что программа считает файл из правильного места вне зависимости от того, откуда она была запущена (например, из другой папки или через демона).

Собранные через cx_Freeze скрипты обычно либо неправильно интерпретируют глобальную переменную __file__, либо вообще ее не знают. Последнее как раз произошло, когда я попробовал собрать и запустить исполняемый файл из простенького тестового скрипта:

Проблема оказалась известной. Достаточно было слегка пропатчить мою программу:

В результате, всё завелось с полпинка! Отлично. Простая часть завершена! Переходим к повторению всего этого в виртуальной среде!

Ох уж эти виртуальные среды!

Если вы не пользуетесь virtualenv, полагаю, вас не очень заинтересует дальнейшее чтение этой статьи. Особенность заключается не только в установке cx_Freeze в среду, но и в запуске его таким образом, чтобы он пользовался именно зависимостями из среды, а не системными.

На заметку

Пользоваться средой в шелле (запускается через «source env/bin/activate») нам не придётся. Я пробовал, эффекта это не дало.

Установка

/path/to/my/project/env/bin/python3 setup.py install

Не очень удобно. Пришлось прописывать путь к интерпретатору Питона в нашей среде. Но всё установилось.

Сборка

Однострочный метод, описанный выше, здесь не пройдёт. Нужно использовать другой — через установочный файл.

Файл этот, в краткой форме, которая мне была вполне достаточна, выглядит следующим образом:

Самое главное здесь, это задать MAIN_SCRIPT_NAME, которая соответствует имени главного файла нашей программы.

Помещаем этот скрипт в папку проекта и переходим туда. Запускаем:

Источник

how to use cx_freeze in linux to create a package to be used in windows

how to use cx_freeze in linux to create a one package to be used in windows like .exe or .bin file. I tested cx_freeze in linux but that make package for linux and in windows is unknown.

and this is file that maked :

that is running only in linux.

Is there any way to use cx_freeze for making exe or bin package ?

Or any alternative way instead of cx_freeze to make one bin file to execute in other platform independent?

I use python3(3.x).

3 Answers 3

I’ve been trying to get cx_freeze properly working on windows in every way possible but with no luck. I was trying to do what you are doing now using Ubuntu but I found this, sadly: https://cx_freeze.readthedocs.org/en/latest/faq.html#problems-with-running-frozen-programs

» Freezing for other platforms

cx_Freeze works on Windows, Mac and Linux, but on each platform it only makes an executable that runs on that platform. So if you want to freeze your program for Windows, freeze it on Windows; if you want to run it on Macs, freeze it on a Mac.

At a pinch, you can try to make a Windows executable using Wine. Our experience is that you need to copy some files in manually after cx_Freeze has run to make the executable work. We don’t recommend this option. » I guess the only option is to try doing it with wine? Have you had any luck?

Источник

jenyay.net

Софт, исходники и фото

Создание запускаемых файлов из скриптов на языке Python с помощью cx_Freeze

Содержание

1. Введение

Python — отличный язык программирования для широкого круга задач, начиная от автоматизации рутинных действий до создания web- или настольных приложений с графическим интерфейсом. Но Python — интерпретируемый язык, а это значит, что если вы хотите распространять ваше приложение, то у пользователя должен быть установлен интерпретатор, на вход которого он должен подать исходные коды вашей программы. Если вы разрабатываете приложение под Linux или основная масса пользователей вашей программы — айтишники (программисты, админы и им сочувствующие), то требование установить интерпретатор Python скорее всего их не испугает. А вот заставлять устанавливать Python, а, возможно, еще и дополнительные библиотеки обычных пользователей — сомнительная идея.

Однако, Python хорош еще тем, что ядро интерпретатора достаточно компактное, оно умещается в единственную dll-ку размером 3.5 МБ + дополнительные модули. Это позволяет сделать такой хак: скопируем в отдельную папку файл PythonXX.dll (где XX — номер версии интерпретатора Python) и также скомпилированные файлы *.pyc, созданные из исходных файлов вашего приложения и используемых модулей, а затем рядом с этими файлами создадим запускаемый файл .exe, который будет подменять и перенаправлять вызовы интерпретатора в скопированную dll-ку (это очень грубое представление работы создаваемого файла .exe, но для простоты оставим так). Набор этих файлов можно передавать конечному пользователю, он запустит запускаемый файл и даже не будет догадываться, что «под капотом» работает интерпретатор Python.

Именно это и делает библиотека cx_Freeze, причем такой прием эта библиотека умеет применять для Windows, Linux и Mac OS. Эта статья будет посвящена использованию данной библиотеки. На простейших примерах мы рассмотрим основы работы с этой библиотекой cx_Freeze и различные сценарии ее использования.

Читайте также:  Windows ebd system file

Все примеры в этой статье тестировались на Python 3.6 и cx_Freeze 5.0.2. cx_Freeze пока еще умеет работать с Python 2.7, но судя по коммитам на github, следующая версия cx_Freeze 6 будет работать только с Python 3.5 и выше.

2. Установка

Устанавливается cx_Freeze стандартно через pip. Если вы хотите установить cx_Freeze глобально для всех пользователей системы, то нужно выполнить в консоли команду

Разумеется, для этого у вас должны быть права администратора, и консоль должна быть запущена от администратора.

Или вы можете установить cx_Freeze только для вашего пользователя, тогда админские права не понадобятся:

В реальном проекте идеологически более верно установить cx_Freeze внутри virtualenv, но в этом случае могут быть некоторые проблемы (например).

3. Первый пример

Теперь, когда cx_Freeze установлен, можно приступать к изучению возможностей этой библиотеки. Все примеры из статьи вы можете найти на github. Примеры последовательно пронумерованы в том порядке, как они описаны в статье. Приложение, которое мы будем упаковывать в запускаемые файлы, будет называться example.py.

Для начала создадим простейший python-скрипт с именем example.py, который не импортирует никакие модули (Example 01 на github):

if __name__ == ‘__main__’ :
print ( ‘Hello world!’ )

Скорее всего нет смысла описывать, что делает данный скрипт. 🙂 Желающие убедиться, что скрипт работает, могут выполнить команду:

Если у вас установлено несколько версий Python, то под Windows можно воспользоваться утилитой py и явно указать номер версии интерпретатора:

Давайте упакуем наш очень полезный скрипт в запускаемый файл, который можно будет передать пользователю. Для этого создадим файл setup.py со следующим содержимым:

from cx_Freeze import setup , Executable

executables = [ Executable ( ‘example.py’ ) ]

setup ( name = ‘hello_world’ ,
version = ‘0.0.1’ ,
description = ‘My Hello World App!’ ,
executables = executables )

Имя скрипта для сборки может быть произвольным, но обычно принято называть его setup.py, и мы будем придерживаться этого правила. Те, кто создавал Python-пакеты с помощью утилит distutils или setuptools, увидят в работе с cx_Freeze что-то знакомое.

Итак, в файле setup.py мы импортируем из модуля cx_Freeze функцию setup и класс Executable. Самое главное здесь — это функция setup, в нее передаются все параметры, которые описывают сборку. В параметрах функции setup мы указываем имя приложения (параметр name), номер версии (параметр version), краткое описание приложения (параметр description), а также параметр executables, который должен быть списком экземпляров класса Executable. Почему тут должен быть именно список, и не достаточно одного экземпляра класса Executable будет описано чуть позже в разделе Сборка нескольких запускаемых файлов.

Конструктор класса Executable может принимать достаточно большое количество параметров. Обязательным параметром является только имя запускаемого python-файла. Если ваша программа состоит из большого количества скриптов, то указывать нужно на тот файл, который запускал бы пользователь, если бы он запускал приложение из исходников. Полностью конструктор класса Executable выглядит следующим образом (класс описан в файле freezer.py исходников cx_Freeze):

Некоторыми из этих параметров мы еще воспользуемся, а некоторые останутся за рамками статьи, назначение многих из них понятно из названия переменных.

Чтобы создать запускаемый файл, запустим консоль и перейдем в папку, где лежит файл setup.py. Затем нужно выполнить команду

На экран будет выведено достаточно много теста:

В довольно большом логе работы можно увидеть, какие модули Python попали в сборку, а каких по мнению cx_Freeze не хватает. Чаще всего на этот вывод можно не обращать внимания, если нет каких-либо ошибок.

После запуска скрипта сборки, если все прошло успешно (если нет сообщений об ошибках), рядом с файлами example.py и setup.py должна появиться папка build, а в ней папка, имя которой зависит от версии Python. Например, если сборка запускалась с помощью 32-битной версии интерпретатора Python 3.6, то будет создана папка exe.win32-3.6, а в ней огромное количество файлов и папок.

Среди файлов можно увидеть файл example.exe — файл, который будут запускать пользователи. Попробуйте его запустить — откроется консольное окно, в котором промелькнет фраза «Hello world!»

Рядом с запускаемым файлом расположился файл с ядром интерпретатора Python — python36.dll, а также файл python36.zip — архив, в котором хранятся модули Python, скомпилированные в файлы *.pyc. Также в корне находятся динамические загружаемые библиотеки *.pyd и папки с пакетами, которые не попали в файл python36.zip. Если открыть этот архив, то можно увидеть, что он содержит файлы *.pyc.

По умолчанию cx_Freeze в архив помещает одиночные модули, а пакеты помещает в корень папки сборки. В данный момент в сборку попало очень много лишних модулей, который на самом деле не используются в программе. Например, среди модулей можно увидеть unittest, logging, xml, urllib и другие, которые явно не используются в нашей простой программе. Скоро мы научимся удалять лишние модули из сборки и вручную добавлять необходимые.

4. Добавление файлов Microsoft Visual C++ Redistributable

Интерпретатор Python компилируется под Windows с помощью Microsoft Visual C++, поэтому для того, чтобы пользователи могли запускать собранное вами приложение, у них должен установлен Microsoft Visual C++ Redistributable Package, который они должны скачать с сайта Microsoft. Это не очень удобно. Ситуация усугубляется тем, что разные версии Python компилируются с помощью разных версий компилятора.

Чтобы решить эту проблему вы можете поставлять с вашим дистрибутивом необходимые файлы *.dll. Например, для Python 3.6 достаточно скопировать файл vcruntime140.dll из папки с установленным Python. Для того, чтобы не делать эту вручную, cx_Freeze может делать это за вас, для этого надо добавить новый для нас параметр в функцию setup скрипта сборки setup.py. Исправленный скрипт сборки теперь будет выглядеть следующим образом (Example 02):

from cx_Freeze import setup , Executable

executables = [ Executable ( ‘example.py’ ) ]

options = <
‘build_exe’ : <
‘include_msvcr’ : True ,
>
>

setup ( name = ‘hello_world’ ,
version = ‘0.0.2’ ,
description = ‘My Hello World App!’ ,
executables = executables ,
options = options )

В функцию setup был добавлен новый параметр options, который должен быть словарем. Этот словарь содержит вложенные словари, описывающие особенности сборки для разных операционных систем и типов сборки (cx_Freeze кроме запускаемых файлов может создавать инсталяторы). Все возможные параметры можно найти в документации, некоторые из этих параметров мы еще будем использовать в дальнейшем.

Пока мы добавили единственный параметр в словарь build_exe — ‘include_msvcr’: True. Этот параметр говорит cx_Freeze, что нужно скопировать необходимые файлы *.dll из Microsoft Visual C++ Redistributable.

Но в последних версиях cx_Freeze есть некоторые непонятные моменты, связанные с этим параметром. По идее после запуска нового скрипта сборки с помощью команды

должна создаться та же самая сборка, что и в предыдущем примере, но только в папке с программой должен появиться файл vcruntime140.dll (для Python 3.6). Во время написания этой статьи (напомню, что для тестирования примеров использовался cx_Freeze 5.0.2) этот файл не копировался. На github есть несколько обсуждений (#275), где говорится, что этот файл не копируется при использовании virtualenv. Я пробовал запускать эти примеры и без virtualenv, файл vcruntime140.dll все равно не копировался. В одном из следующих примеров, когда мы будем собирать скрипт, создающий графический интерфейс с помощью библиотеки wxPython, этот файл появится. С чем связано такое поведение — пока загадка. Но при создании своих сборок имейте это в виду, может быть нужно будет копировать файлы Microsoft Visual C++ Redistributable вручную. В дальнейших примерах для общности везде будет добавлен параметр include_msvcr.

5. Избавляемся от лишних модулей

Как мы видим, несмотря на то, что наш исходный скрипт Hello World явно не импортирует никакие модули, в сборку попало достаточно много файлов *.pyc и *.pyd. Некоторые из них нам явно не нужны (например, unittest, logging и другие). Полный размер сборки сейчас составляет 9.05 МБ, что для простого Hello World кажется излишним, хотя при современных размерах жестких дисков скорее всего не будет проблемой.

Читайте также:  Windows 10 веб средство просмотра классических приложений

cx_Freeze позволяет указать, какие модули не надо включать в создаваемую сборку. Сразу скажу, что этой возможностью надо пользоваться осторожно, особенно для больших программах. Python — язык с динамической типизацией и заранее нельзя сказать, какие модули понадобятся, а какие нет. Тут нужно все тестировать. Некоторые модули исключить не удастся, и cx_Freeze во время сборки напишет ошибку, другие модули можно не включить в сборку, но на самом деле они окажутся нужными (например, они могут использоваться другими модулями, которые вы используете), и в этом случае вы получите ошибку во время выполнения программы. Это особенно неприятно для больших программ. Таким образом вы можете исключить модуль, который используется в редком случае, и из-за этого не сразу обнаружить ошибку. Поэтому лучше убирать из сборки только те модули, в которых вы 100% уверены, что они не используются (модуль unittest обычно таким является).

Чтобы исключить какие-либо модули из сборки, в словарь параметров build_exe нужно добавить ключ excludes, значением которого должен быть список строк с именами модулей, которые нужно исключить. Давайте для начала исключим модули, которые нам явно не нужны. Добавим параметр excludes с небольшим списком модулей (Example 03):

from cx_Freeze import setup , Executable

executables = [ Executable ( ‘example.py’ ) ]

excludes = [ ‘unicodedata’ , ‘logging’ , ‘unittest’ , ’email’ , ‘html’ , ‘http’ , ‘urllib’ ,
‘xml’ , ‘bz2’ ]

options = <
‘build_exe’ : <
‘include_msvcr’ : True ,
‘excludes’ : excludes ,
>
>

setup ( name = ‘hello_world’ ,
version = ‘0.0.3’ ,
description = ‘My Hello World App!’ ,
executables = executables ,
options = options )

После сборки заходим в папку build\exe.win32-3.6\ или аналогичную ей и видим, что количество файлов и папок заметно уменьшилось:

В архиве python36.zip количество файлов тоже немного уменьшилось:

Общий размер сборки теперь составляет 5.93 МБ — размер уже уменьшился на треть. Обязательно надо убедиться, что программа работает.

В реальном проекте, возможно, стоит на этом остановиться и не рисковать сломать программу, удаляя более мелкие модули. Но поскольку у нас очень простая программа, мы можем пойти дальше и путем перебора попробовать удалить как можно больше ненужных модулей. Через несколько (десятков?) итераций удаления и восстановления модулей получился следующий скрипт сборки (Example 04):

from cx_Freeze import setup , Executable

executables = [ Executable ( ‘example.py’ ) ]

excludes = [ ‘unicodedata’ , ‘logging’ , ‘unittest’ , ’email’ , ‘html’ , ‘http’ , ‘urllib’ ,
‘xml’ , ‘pydoc’ , ‘doctest’ , ‘argparse’ , ‘datetime’ , ‘zipfile’ ,
‘subprocess’ , ‘pickle’ , ‘threading’ , ‘locale’ , ‘calendar’ , ‘functools’ ,
‘weakref’ , ‘tokenize’ , ‘base64’ , ‘gettext’ , ‘heapq’ , ‘re’ , ‘operator’ ,
‘bz2’ , ‘fnmatch’ , ‘getopt’ , ‘reprlib’ , ‘string’ , ‘stringprep’ ,
‘contextlib’ , ‘quopri’ , ‘copy’ , ‘imp’ , ‘keyword’ , ‘linecache’ ]

options = <
‘build_exe’ : <
‘include_msvcr’ : True ,
‘excludes’ : excludes ,
>
>

setup ( name = ‘hello_world’ ,
version = ‘0.0.4’ ,
description = ‘My Hello World App!’ ,
executables = executables ,
options = options )

После его запуска с помощью команды python setup.py build сборка будет выглядеть следующим образом:

А в архиве python36.zip остались лишь следующие модули:

В архиве осталось всего 19 файлов из 100 первоначальных. Теперь сборка занимает 3.7 МБ. По-моему, неплохо. Но это еще не все.

Мы видим, что часть модулей находится в архиве python36.zip , а часть в отдельных папках в папке сборки. Это может быть неприятно из эстетических соображений, если вы не хотите видеть лишние служебные файлы и папки в сборке. На этот случай у cx_Freeze есть еще один параметр, который указывает, какие модули он должен обязательно помещать в архив. Но имейте в виду, что распаковка архива при работе программы тоже будет занимать время, поэтому запуск программы с заархивированными модулями будет медленнее. Насколько медленнее — надо измерять, возможно, скорость будет не заметна для пользователей (скорее всего так и будет).

Чтобы указать, какие модули нужно обязательно поместить в архив, используется элемент с именем zip_include_packages словаря параметров build_exe . Этот элемент словаря должен содержать список строк с именами модулей (пакетов), которые нужно поместить в архив. В нашем случае скрипт сборки преобразуется к следующему виду (Example 05):

from cx_Freeze import setup , Executable

executables = [ Executable ( ‘example.py’ ) ]

excludes = [ ‘unicodedata’ , ‘logging’ , ‘unittest’ , ’email’ , ‘html’ , ‘http’ , ‘urllib’ ,
‘xml’ , ‘pydoc’ , ‘doctest’ , ‘argparse’ , ‘datetime’ , ‘zipfile’ ,
‘subprocess’ , ‘pickle’ , ‘threading’ , ‘locale’ , ‘calendar’ , ‘functools’ ,
‘weakref’ , ‘tokenize’ , ‘base64’ , ‘gettext’ , ‘heapq’ , ‘re’ , ‘operator’ ,
‘bz2’ , ‘fnmatch’ , ‘getopt’ , ‘reprlib’ , ‘string’ , ‘stringprep’ ,
‘contextlib’ , ‘quopri’ , ‘copy’ , ‘imp’ , ‘keyword’ , ‘linecache’ ]

zip_include_packages = [ ‘collections’ , ‘encodings’ , ‘importlib’ ]

options = <
‘build_exe’ : <
‘include_msvcr’ : True ,
‘excludes’ : excludes ,
‘zip_include_packages’ : zip_include_packages ,
>
>

setup ( name = ‘hello_world’ ,
version = ‘0.0.5’ ,
description = ‘My Hello World App!’ ,
executables = executables ,
options = options )

Запускаем сборку и смотрим на ее результат:

Осталось всего лишь три файла!

Указанные в скрипте сборки модули переместились в файл python36.zip:

Теперь сборка занимает всего лишь 3.45 МБ — по сравнению с исходными 9 МБ размер сократился почти в 3 раза. Еще раз напомню, что в сборку еще не были включены файлы из Microsoft Visual C++ Redistributable, которые почему-то не были помещены автоматически библиотекой cx_Freeze. Ну и, конечно, в этом примере было применено очень агрессивное исключение модулей, которые могут использоваться во многих других модулях. Обычно этого делать не стоит, чтобы не получить неожиданную ошибку. К тому же многие файлы *.pyc занимают всего лишь десятки кБ, из-за которых нет смысла рисковать.

6. Наводим красоту в сборке

Мы создали запускаемую сборку нашей программы. По умолчанию она помещается в папку с именем вроде build\exe.win32-3.6\ , имя которой зависит от версии Python, для которой происходила сборка. Во многих случаях можно на этом остановиться, но в больших проектах создание такой сборки — это лишь один промежуточный этап автоматического создания дистрибутива. После этого полученную сборку, возможно, нужно будет отправить на сервер для тестирования, может быть нужно будет запустить локальные тесты или создать из сборки инсталятор. Поэтому может оказаться, что такое имя папки неудобно или нужно сохранить сборку на другом диске. Все это, конечно, можно сделать сторонними скриптами, но cx_Freeze позволяет настраивать, куда будет помещена полученная сборка.

Давайте изменим файл setup.py, таким образом, чтобы создаваемая сборка помещалась, например, в папку build_windows рядом со скриптами. Для этого снова нужно добавить новый параметр в словарь build_exe. Этот параметр тоже должен называться build_exe и хранить строку с папкой, куда должна помещаться сборка (Example 06):

from cx_Freeze import setup , Executable

executables = [ Executable ( ‘example.py’ ) ]

excludes = [ ‘unicodedata’ , ‘logging’ , ‘unittest’ , ’email’ , ‘html’ , ‘http’ , ‘urllib’ ,
‘xml’ , ‘pydoc’ , ‘doctest’ , ‘argparse’ , ‘datetime’ , ‘zipfile’ ,
‘subprocess’ , ‘pickle’ , ‘threading’ , ‘locale’ , ‘calendar’ , ‘functools’ ,
‘weakref’ , ‘tokenize’ , ‘base64’ , ‘gettext’ , ‘heapq’ , ‘re’ , ‘operator’ ,
‘bz2’ , ‘fnmatch’ , ‘getopt’ , ‘reprlib’ , ‘string’ , ‘stringprep’ ,
‘contextlib’ , ‘quopri’ , ‘copy’ , ‘imp’ , ‘keyword’ , ‘linecache’ ]

zip_include_packages = [ ‘collections’ , ‘encodings’ , ‘importlib’ ]

options = <
‘build_exe’ : <
‘include_msvcr’ : True ,
‘excludes’ : excludes ,
‘zip_include_packages’ : zip_include_packages ,
‘build_exe’ : ‘build_windows’ ,
>
>

setup ( name = ‘hello_world’ ,
version = ‘0.0.6’ ,
description = ‘My Hello World App!’ ,
executables = executables ,
options = options )

Теперь после создания сборки рядом с файлами example.py и setup.py появится папка build_windows, где будет находиться созданная сборка, ничем не отличающаяся от предыдущего примера.

По умолчанию cx_Freeze создает запускаемый файл, имя которого (без расширения) совпадает с именем запускаемого скрипта. То есть в нашем случае — example.exe, поскольку наш запускаемый сприпт называется example.py. Часто нужно дать запускаемому файлу другое имя. Сделать это тоже очень просто, достаточно добавить еще один параметр, но на этот раз в конструктор класса Executable. Имя нужного нам параметра — targetName. Это должна быть строка, которая содержит имя создаваемого запускаемого файла. Поэтому, если мы хотим, чтобы cx_Freeze создал запускаемый файл hello_world.exe, то предыдущий файл setup.py нужно изменить следующим образом (Example 07):

Читайте также:  Компьютер зависает после 5 минут работы windows

from cx_Freeze import setup , Executable

executables = [ Executable ( ‘example.py’ , targetName = ‘hello_world.exe’ ) ]

excludes = [ ‘unicodedata’ , ‘logging’ , ‘unittest’ , ’email’ , ‘html’ , ‘http’ , ‘urllib’ ,
‘xml’ , ‘pydoc’ , ‘doctest’ , ‘argparse’ , ‘datetime’ , ‘zipfile’ ,
‘subprocess’ , ‘pickle’ , ‘threading’ , ‘locale’ , ‘calendar’ , ‘functools’ ,
‘weakref’ , ‘tokenize’ , ‘base64’ , ‘gettext’ , ‘heapq’ , ‘re’ , ‘operator’ ,
‘bz2’ , ‘fnmatch’ , ‘getopt’ , ‘reprlib’ , ‘string’ , ‘stringprep’ ,
‘contextlib’ , ‘quopri’ , ‘copy’ , ‘imp’ , ‘keyword’ , ‘linecache’ ]

zip_include_packages = [ ‘collections’ , ‘encodings’ , ‘importlib’ ]

options = <
‘build_exe’ : <
‘include_msvcr’ : True ,
‘excludes’ : excludes ,
‘zip_include_packages’ : zip_include_packages ,
‘build_exe’ : ‘build_windows’ ,
>
>

setup ( name = ‘hello_world’ ,
version = ‘0.0.7’ ,
description = ‘My Hello World App!’ ,
executables = executables ,
options = options )

Запускаем сборку и видим, что в папке build_windows вместо example.exe появился файл hello_world.exe:

7. Добавление модулей в сборку

До сих пор мы только исключали лишние модули из создаваемой сборки с помощью параметра excludes словаря build_exe. Однако, импорт модулей в Python может происходить не только с помощью оператора import, но и динамически по имени модуля с помощью функции ‘_import_‘, а может быть импорт будет осуществляться с использованием сложной логики, когда cx_Freeze не сможет понять, что нужно добавить какой-то модуль в сборку.

Давайте изменим наш пример таким образом, чтобы он импортировал модуль json таким образом, что cx_Freeze об этом не узнает (Example 08):

if __name__ == ‘__main__’ :
module = __import__ ( ‘json’ )
print ( ‘Hello world!’ )

Скрипт сборки setup.py пока останется неизменным. Запустим сборку с помощью команды python setup.py build, ошибок при этом не возникнет, будет создана сборка в папке build_windows.

Однако если теперь мы запустим созданный файл hello_world.exe, то в консоль будет выведено информация об исключении:

Traceback (most recent call last):
File «C:\. \Python36\site-packages\cx_Freeze\initscripts\__startup__.py», line 14, in run
module.run()
File «C:\. \Python36\site-packages\cx_Freeze\initscripts\Console.py», line 26, in run
exec(code, m.__dict__)
File «example.py», line 5, in
ModuleNotFoundError: No module named ‘json’

На указанные пути обращать внимания не будем. Для нас сейчас главное, что мы получили ошибку времени исполнения. Надо ее исправлять, а именно нужно добавить модуль json в сборку.

Если для исключения модулей из сборку предназначен параметр excludes, до для включения модуля в сборке используется параметр includes, который тоже должен содержать список модулей, которые нужно добавить в сборку. Параметр includes так же должен входить в словарь build_exe. Добавим модуль json в этот список (Example 08-1):

from cx_Freeze import setup , Executable

executables = [ Executable ( ‘example.py’ , targetName = ‘hello_world.exe’ ) ]

excludes = [ ‘unicodedata’ , ‘logging’ , ‘unittest’ , ’email’ , ‘html’ , ‘http’ , ‘urllib’ ,
‘xml’ , ‘pydoc’ , ‘doctest’ , ‘argparse’ , ‘datetime’ , ‘zipfile’ ,
‘subprocess’ , ‘pickle’ , ‘threading’ , ‘locale’ , ‘calendar’ , ‘functools’ ,
‘weakref’ , ‘tokenize’ , ‘base64’ , ‘gettext’ , ‘heapq’ , ‘re’ , ‘operator’ ,
‘bz2’ , ‘fnmatch’ , ‘getopt’ , ‘reprlib’ , ‘string’ , ‘stringprep’ ,
‘contextlib’ , ‘quopri’ , ‘copy’ , ‘imp’ , ‘keyword’ , ‘linecache’ ]

zip_include_packages = [ ‘collections’ , ‘encodings’ , ‘importlib’ ]

options = <
‘build_exe’ : <
‘include_msvcr’ : True ,
‘excludes’ : excludes ,
‘includes’ : includes ,
‘zip_include_packages’ : zip_include_packages ,
‘build_exe’ : ‘build_windows’ ,
>
>

setup ( name = ‘hello_world’ ,
version = ‘0.0.8’ ,
description = ‘My Hello World App!’ ,
executables = executables ,
options = options )

Создаем сборку, заходим в папку build_windows и видим, что в ней появилась папка с именем json:

Но не спешим радоваться. При попытке запустить hello_world.exe мы получим новую ошибку:

Теперь не хватает модуля для работы с регулярными выражениями re. Если мы посмотрим внимательнее на наш предыдущий файл setup.py, то увидим, что этот модуль мы исключили из сборки с помощью параметра excludes, а этот модуль, оказывается, используется в модуле json. Если мы исключим модуль re из списка excludes, то это тоже не решит проблему, окажется, что еще нужны другие модули, которые вы выкинули из сборки. Я же предупреждал, что не надо увлекаться удалением модулей. Постепенно удаляя имена модулей из списка excludes можно добиться работоспособной сборки. Новый файл setup.py теперь выглядит следующим образом (Example 08-2):

from cx_Freeze import setup , Executable

executables = [ Executable ( ‘example.py’ , targetName = ‘hello_world.exe’ ) ]

excludes = [ ‘unicodedata’ , ‘logging’ , ‘unittest’ , ’email’ , ‘html’ , ‘http’ , ‘urllib’ ,
‘xml’ , ‘pydoc’ , ‘doctest’ , ‘argparse’ , ‘datetime’ , ‘zipfile’ ,
‘subprocess’ , ‘pickle’ , ‘threading’ , ‘locale’ , ‘calendar’ ,
‘tokenize’ , ‘base64’ , ‘gettext’ ,
‘bz2’ , ‘fnmatch’ , ‘getopt’ , ‘string’ , ‘stringprep’ ,
‘contextlib’ , ‘quopri’ , ‘copy’ , ‘imp’ , ‘linecache’ ]

zip_include_packages = [ ‘collections’ , ‘encodings’ , ‘importlib’ ]

options = <
‘build_exe’ : <
‘include_msvcr’ : True ,
‘excludes’ : excludes ,
‘includes’ : includes ,
‘zip_include_packages’ : zip_include_packages ,
‘build_exe’ : ‘build_windows’ ,
>
>

setup ( name = ‘hello_world’ ,
version = ‘0.0.8’ ,
description = ‘My Hello World App!’ ,
executables = executables ,
options = options )

Из списка excludes были убраны следующие модули: re, functools, operator, keyword, heapq, reprlib, weakref.

Создаем сборку и получаем теперь уже работоспособное приложение. Если мы зайдем в папку build_windows, то увидим, что внешне ничего не изменилось, в ней из перечисленных модулей значится только папка json, остальные модули были помещены в архив python36.zip:

И для аккуратности сделаем так, чтобы модуль json тоже был помещен в архив python36.zip, добавим строку ‘json’ в параметр zip_include_packages (Example 08-3):

from cx_Freeze import setup , Executable

executables = [ Executable ( ‘example.py’ , targetName = ‘hello_world.exe’ ) ]

excludes = [ ‘unicodedata’ , ‘logging’ , ‘unittest’ , ’email’ , ‘html’ , ‘http’ , ‘urllib’ ,
‘xml’ , ‘pydoc’ , ‘doctest’ , ‘argparse’ , ‘datetime’ , ‘zipfile’ ,
‘subprocess’ , ‘pickle’ , ‘threading’ , ‘locale’ , ‘calendar’ ,
‘tokenize’ , ‘base64’ , ‘gettext’ ,
‘bz2’ , ‘fnmatch’ , ‘getopt’ , ‘string’ , ‘stringprep’ ,
‘contextlib’ , ‘quopri’ , ‘copy’ , ‘imp’ , ‘linecache’ ]

zip_include_packages = [ ‘collections’ , ‘encodings’ , ‘importlib’ , ‘json’ ]

options = <
‘build_exe’ : <
‘include_msvcr’ : True ,
‘excludes’ : excludes ,
‘includes’ : includes ,
‘zip_include_packages’ : zip_include_packages ,
‘build_exe’ : ‘build_windows’ ,
>
>

setup ( name = ‘hello_world’ ,
version = ‘0.0.8’ ,
description = ‘My Hello World App!’ ,
executables = executables ,
options = options )

Теперь сборка выглядит аккуратно и состоит всего из трех файлов:

А в архиве python36.zip появился модуль json:

8. Сборка нескольких запускаемых файлов

Давайте вернемся к вопросу о том, зачем в качестве параметра executables функции setup должен быть передан список экземпляров класса Executable, а не единственный экземпляр класса. Это полезно в тех случаях, когда ваше приложение состоит из нескольких запускаемых файлов. Например, это может быть основная программа и дополнительная программа для обновления основной программы, или может быть ваше приложение — это набор небольших утилит, написанных на Python. В этом случае для каждой такой программы надо делать отдельную сборку, но как быть с архивом модулей (python36.zip или аналогичного), ведь у каждой программы будет свой список импортируемых модулей? Именно поэтому cx_Freeze позволяет указывать список создаваемых запускаемых файлов, а в архив модулей будут помещены все необходимые модули для всех приложений.

Сделаем два простых скрипта в одной папке (Example 09).

if __name__ == ‘__main__’ :
print ( ‘Hello world 01!’ )

if __name__ == ‘__main__’ :
print ( ‘Hello world 02!’ )

Скрипт hello_01.py явно импортирует модуль json, поэтому в файле setup.py мы не будем использовать параметр includes — cx_Freeze сам найдет все необходимые модули. Для скрипта hello_02.py модуль json не требуется. Для каждого из этих модулей мы должны создать свой экземпляр класса Executable в setup.py, а остальное нам уже знакомо:

from cx_Freeze import setup , Executable

executables = [ Executable ( ‘hello_01.py’ , targetName = ‘hello_world_01.exe’ ) ,
Executable ( ‘hello_02.py’ , targetName = ‘hello_world_02.exe’ ) ,
]

excludes = [ ‘unicodedata’ , ‘logging’ , ‘unittest’ , ’email’ , ‘html’ , ‘http’ , ‘urllib’ ,
‘xml’ , ‘pydoc’ , ‘doctest’ , ‘argparse’ , ‘datetime’ , ‘zipfile’ ,
‘subprocess’ , ‘pickle’ , ‘threading’ , ‘locale’ , ‘calendar’ ,
‘tokenize’ , ‘base64’ , ‘gettext’ ,
‘bz2’ , ‘fnmatch’ , ‘getopt’ , ‘string’ , ‘stringprep’ ,
‘contextlib’ , ‘quopri’ , ‘copy’ , ‘imp’ , ‘linecache’ ]

zip_include_packages = [ ‘collections’ , ‘encodings’ , ‘importlib’ , ‘json’ ]

options = <
‘build_exe’ : <
‘include_msvcr’ : True ,
‘excludes’ : excludes ,
‘zip_include_packages’ : zip_include_packages ,
‘build_exe’ : ‘build_windows’ ,
>
>

setup ( name = ‘hello_world’ ,
version = ‘0.0.9’ ,
description = ‘My Hello World App!’ ,
executables = executables ,
options = options )

Запускаем сборку и видим, что в папке build_windows появились файлы hello_world_01.exe и hello_world_02.exe:

А в архиве python36.zip имеется модуль json, который нужен только для hello_world_01.exe:

Источник

Оцените статью