I know nothing on this subject, but I need suggestions about the best tools or method for creating a setup program that installs python, some custom python modules, some other python modules such as PIL, and some EXE dependencies, all living on a network repository, on windows machines. In the repository are installers for python (msi file), PIL (exe file), the custom python modules (pyc files), and two windows executables (and exe file and a zip file). Any advice welcome.
问题:
回答1:
You can do this with any of the installer applications out there. Each of the dependent installers has a silent install option, so your installer just needs to invoke the installers for each of the dependencies in the right order. I won't recommend any windows installer application in particular because I don't like any of them, but they will all do what you want.
The other option you have is to use py2exe which can bundle everything into a single exe file that runs in its own python environment. The plus side to this is you don't have to worry about installing Python in the users environment and have the user potentially uninstall python and then have your app stop working because everything is in a standalone environment.
Other ways that I have seen this done is with a custom exe written in whatever compiled Windows Language you prefer that does all this for you, but this takes a lot of work.
You could also get the advantage of the py2exe route with a little work on an installer you write with either an installer app or a standalone exe that handles the install, by manually placing the python.exe, dll and related code in the proper directories relative to your application code. You may have to mess with your PYTHONPATH environment setting when your app starts to get everything working, but this way you don't have to worry about installing Python and whether the user already has Python installed or if they uninstall it because then you have the Python version you need bundled with your app.
One thing to note is that if you are worried about size the Python installer itself is about 10 MB before any dependencies, but a lot of that is not relevant to an end user using your app, There is no Python Runtime Environment installer like there is a Java runtime Environment installer that just install what you need to run Python, you always get the development tools.
Hope this helps a little.
回答2:
Nice response Michael.
But, py2exe can intimidate the more novice user, for them it may be easier to use pyinstaller 1.5.1 (There's 2.x available, but it over complicated itself, although it has simple and powerful library hooking [ which you will most likely not need]).
All pyinstaller requires is to be Configured (Automatic with Configure.py), and the main source file of your executable, and it will take care of the rest.
After downloading pyinstaller, you can set it's path as an environment variable, and you can now make an executable in about three lines in a batch or cmd.
I usually have a batch script made that will allow me to easily change a few labels, drop the script in the directory of my choosing, and make the executable in one click.
Your script might look something like:
python %pyinstaller%/Configure.py
python %pyinstaller%/Makespec.py -F --icon=C:\Path\To\MyIcon.ico -n ExecutableName
C:\Path\To\Source\Main.py
python %pyinstaller%/Build.py ExecutableName.spec
Also, you may have to include a pseudo pause if Build.py is called before the spec file is available. I put this line:
ping -n 2 127.0.0.1>nul
Between each %pyinstaller% command to make sure that nothing is called before it is ready, and because "pause" requires a key entry to continue. The "-n 2" will pause the script for 1 second before continuing.
After the script is run, it will create two directories (Build, and dist). Your standalone executable will be located in the "dist" folder.
I've used this for all my applications, and have never had a problem, except for with use with PyMC. This had a garbage library import call in one of the modules which stopped all module finders from following the next import, even py2exe wouldn't work. If you encounter something like this, you will most likely have to go into the module source code and fix the garbage. * Chances of this are very slim for most libraries *
-- Edit (2 minutes later) --
After re-reading your question after posting, it seems you want an actual installer.
I would suggest using pyinstaller to make your python executable. The EXE created will include any imports in the main script, so you won't have to include the physical installers for python, PIL, custom modules in the main Installer program ( So long as they are referenced in your script ). Now is the fun part:
You will want to install InnoSetup. It is a free open source program used for developing professional looking installers for windows. The main installer will require a script to run. This may need some reading up on the syntax, but I will try my best to give you the jist.
The syntax of the script is similar to Pascal, and there are usually 6 sections in this script that are used in the installer:
[Setup] , [Files] , [Tasks] , [Icons] , [Run] , and [Code]
The [Setup] section includes all the basic information about your installer:
[Setup]
AppId={{123LKJESA-1441-FAKE-IDNO-THISWONTWRK}
OutputDir=.
OutputBaseFilename=MyInstaller
AppName=ExecutableName
AppVersion=1.0
AppPublisher=YourCompany
AppPublisherURL=http://www.URL.com
AppSupportURL=http://www.URL.com
AppUpdatesURL=http://www.URL.com
DefaultGroupName=A_GroupName
LicenseFile=C:\Path\To\Your\License.txt
DefaultDirName={pf}\MainDirName
WizardImageBackColor=$00001a
SetupIconFile=C:\Path\To\Icon.ico
Compression=lzma
SolidCompression=yes
- Note: That the AppID is unique to your application, if you create a new version, this ID must be the same, or the installer will install a separate exe, and there's a good chance that the uninstaller will break.
Also, DefaultDirName has the key {pf} which stands for Program Files. There are other location keys such available, and can be found on the website Documentation.
[Files] - This section will include any files required for the installer, and it follows a pretty standard format. You will need a Source: and a Destination (DestDir:). Other useful options are CopyMode, which tell the installer what to do on a reinstallation, and Flags: which give even more options on what to do with this file.
Example:
[Files]
Source: C:\Path\to\my\created\python\executable.exe; DestDir: {app}; CopyMode: alwaysoverwrite;
Source: C:\Path\to\directory\of\files; DestDir: {localapp}; CopyMode: alwaysoverwrite; Flags: recursesubdirs;
- The {app} key here in the first source destdir is a reference to the destination of the application.
- The {localapp} key will store all the files in my directory given, in the users local app data file, which can be referenced by the python application.
[Tasks] will give the user options to select certain tasks for this application. In the example below I want the user to select whether or not they want to have a desktop icon.
[Tasks]
Name: "desktopicon" Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}";
The [Icons] section is pretty self explanatory, and can be looked up in the online docs (also this post is getting too long)
Last the [Code] section
This section isn't completely necessary, as the installer will run in default mode with out it. But, if you want to create a more complex installer, here is where you will do it. This is the section which can be handled by an ordinary programmer, but if you have a background with Pascal it will really help. Here, you can create custom windows, setup AfterInstall and BeforeInstall checks (such as check registries if certain programs are already installed, else start another installer before continuing)
-- Edit 2 --
In my haste I forgot about the [Run] section. The [Run] section give the user the option to run the application immediately after install. Here is an example that will show a check box on the last page, that is initially unchecked, for the user to select if they want to run the program.
[Run]
Filename: "{app}\ExecutableName.exe"; Flags: nowait postinstall unchecked
*ReCap: A good application and installer should not require the user to install python and the separate libraries used. Using py2exe or pyinstaller will create a standalone executable so none of this will need to be installed on the end-users machine. InnoSetup will allow you to create the installer, and place that executable (and any other non-python essential sources) in a desired location, so that it can run exactly the same as it did while still in .pyc files from your machine.
** Before deploying your application it is a good idea to test your application and installer on different machine (or create virtual machines). Eg. The {localappdata} key on windows 7 refers to "C:\Users\UserName\AppData\Local" and on XP it refers to "C:\Documents and Settings\UserName\Local" (trying to remember off the top of my head so might be wrong). So there's a good chance that if your program is accessing the user's local application data to store files, that the path link will be broken on XP, using os.environ['LOCALAPPDATA']. On XP the InnoSetup key {userappdata} will point to "C:\Documents and Settings\UserName\Application Data", which is in the right direction of where the python os.environ mapping will be pointing. Using "{userappdata}\Local" will yield the right path. But on Windows 7, {userappdata} will point to "C:\Users\UserName\AppData\Roaming". So if the application will be backward compatible with windows versions, you will need to setup a bit of code in the [Code] section, to determine the correct version, and set a boolean flag on which key to use.
The URL for the online Documents is:
http://www.jrsoftware.org/ishelp/
I hope that you (or others) find this useful, because it is a powerful tool, as all the files you include in the [Files] section will be packaged up into the standalone installer, and will appear in the destination you give it. Even though this may be a little long winded, it should give you a real good start on making executables and packaging it with an installer.
Good Luck!