Size: 2829
Comment: make the problem more visible https://sourceforge.net/tracker/?func=detail&atid=115583&aid=3004240&group_id=15583
|
Size: 3265
Comment: sys.modules may have issues when packaging things up. I found I had to import the sys module to get things to compile...
|
Deletions are marked like this. | Additions are marked like this. |
Line 4: | Line 4: |
py2exe fails to find imported win32com.shell module. | `py2exe` doesn't find imported `win32com.shell` module, and creates invalid distribution without this file. As a result, an application that uses this module may crash at random or miss some features. |
Line 33: | Line 33: |
win32com does some magic in order to allow loading of COM extensions during run time. The actual extensions reside in the win32comext directory under site-packages and can't be loaded directly. win32com's [[http://docs.python.org/tut/node8.html#SECTION008430000000000000000|__path__]] variable has been changed to point to both win32com and win32comext. py2exe's modulefinder can't handle runtime changes in __path__ so we have to tell it about the change beforehand. | `win32com` does some magic in order to allow loading of COM extensions during run time. The actual extensions reside in the `win32comext` directory under site-packages and can't be loaded directly. `win32com`'s [[http://docs.python.org/tutorial/modules.html#packages-in-multiple-directories|__path__]] variable has been changed to point to both `win32com` and `win32comext`. `py2exe`'s modulefinder can't handle runtime changes in `__path__` so we have to tell it about the change beforehand. |
Line 37: | Line 37: |
Without shame I browsed [[http://cvs.sourceforge.net/viewcvs.py/spambayes/|Spambayes source code]] and found the code to fix it. | Without shame I browsed [[http://spambayes.svn.sourceforge.net/viewvc/spambayes/trunk/spambayes/|Spambayes source code]] and found the code to fix it. |
Line 41: | Line 41: |
# By default, the installer will be created as dist\Output\setup.exe. import time import sys |
# ... |
Line 47: | Line 43: |
Line 49: | Line 44: |
# py2exe 0.6.4 introduced a replacement modulefinder. # This means we have to add package paths there, not to the built-in # one. If this new modulefinder gets integrated into Python, then # we might be able to revert this some day. |
|
Line 50: | Line 49: |
import py2exe.mf as modulefinder import win32com |
try: import py2exe.mf as modulefinder except ImportError: import modulefinder import win32com, sys |
Line 76: | Line 78: |
* Spambayes * Mercurial * hgsvn |
* Spambayes * Mercurial * hgsvn |
Line 82: | Line 84: |
py2exe should detect such well-known problems with well-known modules, and when win32com.shell is missing, a workaround should be automatically applied with a corresponding log message: | `py2exe` should detect such well-known problems with well-known modules, and when `win32com.shell` is missing, a workaround should be automatically applied with a corresponding log message: |
Line 89: | Line 91: |
py2exe should also fail if required modules are missing unless some '--force' key in effect. | `py2exe` should also fail if required modules are missing unless some `--force` key in effect. |
The Problem
py2exe doesn't find imported win32com.shell module, and creates invalid distribution without this file. As a result, an application that uses this module may crash at random or miss some features.
For example version 0.2 of winshell.py from Tim Golden (a thin wrapper around Windows Shell-Functions) starts with:
py2exe reports that something is missing:
The following modules appear to be missing ['Interface', 'intSet', 'mxDateTime.__version__', 'win32com.shell']
and starting the program leaves:
Traceback (most recent call last): File "xxxxxx.py", line 33, in ? File "xxxxxxx.pyo", line 9, in ? File "winshell.pyo", line 27, in ? ImportError: No module named shell
in the log.file.
Explanation
win32com does some magic in order to allow loading of COM extensions during run time. The actual extensions reside in the win32comext directory under site-packages and can't be loaded directly. win32com's __path__ variable has been changed to point to both win32com and win32comext. py2exe's modulefinder can't handle runtime changes in __path__ so we have to tell it about the change beforehand.
Solution
Without shame I browsed Spambayes source code and found the code to fix it.
1 # ...
2 # ModuleFinder can't handle runtime changes to __path__, but win32com uses them
3 try:
4 # py2exe 0.6.4 introduced a replacement modulefinder.
5 # This means we have to add package paths there, not to the built-in
6 # one. If this new modulefinder gets integrated into Python, then
7 # we might be able to revert this some day.
8 # if this doesn't work, try import modulefinder
9 try:
10 import py2exe.mf as modulefinder
11 except ImportError:
12 import modulefinder
13 import win32com, sys
14 for p in win32com.__path__[1:]:
15 modulefinder.AddPackagePath("win32com", p)
16 for extra in ["win32com.shell"]: #,"win32com.mapi"
17 __import__(extra)
18 m = sys.modules[extra]
19 for p in m.__path__[1:]:
20 modulefinder.AddPackagePath(extra, p)
21 except ImportError:
22 # no build path setup, no worries.
23 pass
24
25 from distutils.core import setup
26 import py2exe
27
28 # ...
29 # The rest of the setup file.
30 # ...
And this worked.
Impact
The following products included workaround:
- Spambayes
- Mercurial
- hgsvn
Ideal proposal
py2exe should detect such well-known problems with well-known modules, and when win32com.shell is missing, a workaround should be automatically applied with a corresponding log message:
The following modules appear to be missing ['Interface', 'intSet', 'mxDateTime.__version__', 'win32com.shell'] Applying automatic workaround for known problem with win32com.shell
py2exe should also fail if required modules are missing unless some --force key in effect.