A cx_Freeze Tutorial – Build a Binary Series!
В этой статье, мы рассмотрим cx_Freeze, набор скриптов для разных платформ и цель их "заморозить" скрипты Python в исполняемый файл аналогично py2exe, PyInstaller, и т.д.. We will
freeze one console script and one window (i.e GUI) script, using the
examples from the previous article in this series. If you haven’t done
so already, you can get cx_Freeze
here. Let’s get this party started, shall we?
Getting Started with cx_Freeze
As mentioned on the cx_Freeze website, there are three ways to use
this script. The first is to just use the included cxfreeze script; the
second is to create a distutils setup script (think py2exe) which you
can save for future use; and the third is to work with the internals of
cxfreeze. We will focus on the first two ways of using cx_Freeze. We’ll
begin with the console script:
import configobj
#----------------------------------------------------------------------
def createConfig(configFile):
"""
Create the configuration file
"""
config = configobj.ConfigObj()
inifile = configFile
config.filename = inifile
config['server'] = "http://www.google.com"
config['username'] = "mike"
config['password'] = "dingbat"
config['update interval'] = 2
config.write()
#----------------------------------------------------------------------
def getConfig(configFile):
"""
Open the config file and return a configobj
"""
return configobj.ConfigObj(configFile)
def createConfig2(path):
"""
Create a config file
"""
config = configobj.ConfigObj()
config.filename = path
config["Sony"] = {}
config["Sony"]["product"] = "Sony PS3"
config["Sony"]["accessories"] = ['controller', 'eye', 'memory stick']
config["Sony"]["retail price"] = "$400"
config.write()
if __name__ == "__main__":
createConfig2("sampleConfig2.ini")
All this script does is create a really simple configuration file using Michael Foord’s
configobj
module. You can set it up to read the config too, but for this example,
we’ll skip that. Let’s find out how to build a binary with cx_Freeze!
According to the documentation, all it should take is the following
string on the command line (assuming you are in the correct directory):
cxfreeze config_1.py --target-dir dirName
This assumes that you have “C:\PythonXX\Scripts” on your path. If
not, you’ll either have to fix that or type out the fully qualified
path. Anyway, if the cxfreeze script run correctly, you should have a
folder with the following contents:
As you can see, the total file size should be 4.81 MB or almost 5
megabytes. That was pretty easy. It even picked up the configobj module
without our having to tell it to, something that PyInstaller failed to
do. There are 18 command line arguments you can pass to cx_Freeze to
control how it does things. These range from what modules to include or
exclude, optimization, compression, include a zip file, path
manipulation and more. Now let’s try something a little more advanced.
“Advanced” cx_Freeze – Using a setup.py File
First off we need a script to use. For this one, we’ll use that simple wxPython script from the PyInstaller article:
import wx
########################################################################
class DemoPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
labels = ["Name", "Address", "City", "State", "Zip",
"Phone", "Email", "Notes"]
mainSizer = wx.BoxSizer(wx.VERTICAL)
lbl = wx.StaticText(self, label="Please enter your information here:")
lbl.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD))
mainSizer.Add(lbl, 0, wx.ALL, 5)
for lbl in labels:
sizer = self.buildControls(lbl)
mainSizer.Add(sizer, 1, wx.EXPAND)
self.SetSizer(mainSizer)
mainSizer.Layout()
#----------------------------------------------------------------------
def buildControls(self, label):
""""""
sizer = wx.BoxSizer(wx.HORIZONTAL)
size = (80,40)
font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD)
lbl = wx.StaticText(self, label=label, size=size)
lbl.SetFont(font)
sizer.Add(lbl, 0, wx.ALL|wx.CENTER, 5)
if label != "Notes":
txt = wx.TextCtrl(self, name=label)
else:
txt = wx.TextCtrl(self, style=wx.TE_MULTILINE, name=label)
sizer.Add(txt, 1, wx.ALL, 5)
return sizer
########################################################################
class DemoFrame(wx.Frame):
"""
Frame that holds all other widgets
"""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, wx.ID_ANY,
"cxFreeze Tutorial",
size=(600,400)
)
panel = DemoPanel(self)
self.Show()
#----------------------------------------------------------------------
if __name__ == "__main__":
app = wx.App(False)
frame = DemoFrame()
app.MainLoop()
Now let’s create a
setup.py file in the cx_Freeze style:
from cx_Freeze
import setup, Executable
setup
(
name =
"wxSampleApp",
version =
"0.1",
description =
"An example wxPython script",
executables =
[Executable
("sampleApp.pyw")]
)
As you can see, this is a pretty simple one. We import a couple
classes from cx_Freeze and pass some parameters into them. In this case,
we give the
setup class a name, version, description and and
Executable class.
The Executable class also gets one parameter, the script name that it
will use to create the binary from. To get this to build the binary, you
need to do the following on the command line:
python setup.py build
After running this, you should end up with the following folders:
“build\exe.win32-2.6″. Inside that last folder are 17 files that total
15.3 MB. When you run the sampleApp.exe file, you will notice that we’ve
screwed something up. There’s a console window loading in addition to
our GUI!!! To rectify this, we’ll need to change our setup file
slightly. Take a look at our new one:
from cx_Freeze
import setup, Executable
exe = Executable
(
script=
"sampleApp.pyw",
base=
"Win32GUI",
)
setup
(
name =
"wxSampleApp",
version =
"0.1",
description =
"An example wxPython script",
executables =
[exe
]
)
First off, we separated the
Executable class from the
setup
class and assigned the Executable class to a variable. We also added a
second parameter to the Executable class that is key. That parameter is
called “base”. By setting
base=”Win32GUI”, we are able
to suppress the console window. A good way to learn the many other
options that we can use with cx_Freeze is to use GUI2Exe to generate the
setup.py files for us. The documentation on the cx_Freeze website shows
the many other options that the Executable class takes. Oddly enough, I
couldn’t find any information about what the
setup class takes for arguments other than just the source itself, which has very little comments. Good luck figuring that bit out.
Wrapping Up
Now you should know how to create binaries with cx_Freeze. It’s
pretty easy to do and it’s nice that they’ve created a method to create
binaries in a cross-platform way. Have fun!