SitemapMcMillan Enterprises, Inc. Python Pages Sockets HOWTO Distributing Python Programs Download Python Archives Standalone Executables Installer Release 5 Installer Release 4 Getting Started Installer - Creating Distributions The MEInc.Dist package Installer FAQ Extensions Installer Utilities A Python C++ API Embedding Python Stackless Python MkSQL Import Hooks Java Samples Sponsoring ME Inc. About ME Inc.
|
It doesn't work!
First check extensions page for help on using specific modules and packages with known import hacks.
Then check the warning messages you got when you built. If a module is "not found" that should have been found, tweak your PYTHONPATH before rebuilding. If you see warnings about "__import__", "exec", or "eval" (in modules outside the standard library), check them out for import hacks.
The slow, plodding, painful way through this kind of problem is to:
- Make sure
userunw = 0.
- Set
debug = 1.
- Build.
- Try it with
-v on the command line, in a DOS box with a big buffer (or redirected to a file).
- Between the details that spit out from the debug version of Run and the verbose imports from Python, you should be able to figure out who is calling for what and where.
- Fix the config file to force what's inclusion, or explicitly import the thing in your top level script.
- Go back to step 1.
Another source if information is Builder.log. There's one section in the log for each section in your config. It starts with the state when the section started building, then shows how it was affected by various includes and excludes, and what its final contents were.
You can browse the contents of an exe or pyz with ArchiveViewer or get detailed dependency information from Analyze.
|
The script I'm working with does run time __import__ (or uses execfile or some other perversion), so there *no*way* I can keep trying things, and adding modules one by one!
Oh, freezing IDLE, huh?
OK. Punt. We know IDLE depends on code in Python/Tools/idle. And on the Tk stuff. Oh yeah, and on _tkinter. So we force including Tk, _tkinter, lib-tk and the whole idle directory:
[MYINSTALL]
type= INSTALL
name= Install_spython.exe
bindepends= spythontk.py
zlib = INSTALLZLIB
misc= TK, MYSTANDALONE, _tkinter
debug = 0
includes = tcl80.dll, tk80.dll
excludes = PyWinTypes15.dll, win32api
[MYSTANDALONE]
type= STANDALONE
name= spythontk.exe
script= RunTK.py, spythontk.py
zlib = APPZLIB, IDLEPYZ
userunw = 0
support = 0
debug = 0
[APPZLIB]
name= spythontk.pyz
dependencies= spythontk.py
directories = D:/Programs/Python/Lib
packages = lib-tk
excludes= dospath, posixpath, macpath
[INSTALLZLIB]
name = installzlib.pyz
dependencies = installutils
includes = installutils
excludes = dospath, posixpath, macpath
[IDLEPYZ]
name = idle.pyz
directories = D:/Programs/Python/Tools/idle
Then we build with:
..\..\Builder.py spythontk.cfg ../BuildTk/tk.cfg
|
Huh? That doesn't answer my question!
Sure it does! OK. Too much going on. IDLE is a very extreme example, because Modulefinder fails completely on idle.py. It doesn't even detect that IDLE uses Tk! So I'll break it down.
I force _tkinter and the tcl and tk dlls into the INSTALL section, because they're binary (_tkinter.pyd). Any pure Python is going to go into a .pyz, and the .pyz's will be packed into the STANDALONE.
We need everything from Tools/idle. We could just tell our APPZLIB to include everything from /idle, by adding a directory= option. But I chose instead to make Tools/idle it's own .pyz, and have 2 .pyz's in the standalone. You can go either way. The only "hard" reason for doing it my way is that you can avoid nameclashes within packages if you give each it's own .pyz.
I chose the opposite approach for lib-tk, only because lib-tk is a part of the standard lib.
I also have to include the whole TK machinery. For that, I'm using the extensions mechanism. That is, the BuildTK project creates a CArchive with the basics of Tcl/Tk packed up in it. When you invoke Builder with more than one .cfg file on the command line, it sees them all as one big config. So the misc= TK, in the INSTALL section ties to a section named TK in BuildTK/tk.cfg.
The install script generated when I build will ensure that the TK CArchive tucked into the INSTALL exe will get unpacked, (this happens because Builder "asks" the tk.cfg file if it has instructions on how to install itself). So when the user installs, your app will get a private little Tcl/Tk installation.
There's one more trick, though. To run with this private installation of Tcl/Tk, we need to trick _tkinter into finding it. The BuildTk directory has a tiny script that does that, by manipulating the environment. We stick that into the script= option of the STANDALONE, before the main script.
As I said, IDLE is an extreme case; you shouldn't ever have to go this far!
|
Hey - my code is visible inside the exe!
Protecting your IP, huh?
"Don't worry about people stealing an idea. If it's original, you'll
have to jam it down their throats."
-- Howard Aiken
Hint: If your script is all top level code, then import script will make installer treat your script as a module (no source). If your script uses if __name__ == '__main__':, then the code within that block makes a dandy top level script.
|
It works fine on my machine, but fails with some message about "ordinal number " on the user's machine.
Your user probably has out-of-date .dlls. The most likely problem would be MFC42.DLL. Installer is not in the business of updating MicroSoft .dlls. The easiest solution is probably to have your user install a recent version of IE, (they can de-install later). This updates all the system dlls that Python uses (and then some).
|
|
My Python script is a COM client. How do I get it to work?
New in 4a2: change the scripts option of your exe section to read: scripts = setupcom, myscript.py. Make sure the excludes line does not mention pywintypes and win32api. This does the same as the gen_py section below (but is improved in 4a2).
First, by default all of the top level scripts (Simple, Standalone and Freeze) will exclude PyWinTypesxx.dll and win32api. (This is because any use of os will find these as dependencies, when they're not normally needed.) Use the -win32 flag so they won't be excluded.
Using dynamic.Dispatch
For older releases of Mark's Win32 stuff, that's all you need to do. In newer releases, his import of gen_py has moved from being conditional to being absolute. Skip to the sub-section on gen_py below.
Using makepy generated modules
For newer releases of Mark's stuff, use the -o flag to makepy to specify an output file. Use this file directly. As above, you'll need to skip down to the sub-section on gen_py.
For older releases, figure out what module in your win32com/gen_py directory is yours. Copy it to an application directory and rename it to, e.g., "excel.py". Here's my way of using it (maybe Mark has a better way):
import excel
import win32com.client.dynamic
import pythoncom
dsp, unm = win32com.client.dynamic._GetGoodDispatchAndUserName(
'Excel.Application',
None,
pythoncom.CLSCTX_SERVER)
xl = excel._Application(dsp)
Using gencache.EnsureModule
This method has the advantage that you can generate support (once) on the client machine, so you don't have to worry about mismatches between your makepy-generated module and what's on the target machine. See makepy -i for details. Be warned that generating and compiling the generated code is slow. You might want to make sure it happens as part of installing on the client machine. This method requires the gen_py trick described below.
Using gen_py
Warning: This will not work with Freeze.py, or if you're trying to run directly from a CDROM. It only works with installer_4a1 (and later).
In projects/test/COMclient/test_Standalone (in 4a2, it's now in support) is a script called setupcom.py. This needs to run before your script. Assuming you've used Standalone to generate a config, edit the config and in the section type= STANDALONE, change the script line to read script = setupcom.py, myscript, (you'll need a path there if you don't copy setupcom.py to your app directory). What this script does is extend the Importer so that the win32com.gen_py resolves to a package in the local filesystem in the installation directory. Now when your script runs, the magic imports from gen_py will just work.
If you're using Standalone, you can even set up the gen_py package inside the dist_XXXX directory yourself. If the gen_py directory doesn't exist at run time, setupcom.py will create it (and a dummy __init__.py). If you're using EnsureModule, the generated support will be created the first time, and found in gen_py on subsequent runs.
|
How do I install a COM server?
With 4a4, see MakeCOMServer on the utilities page.
|
|