Kevin Altis wrote:
You probably just want sys.argv[0], in which case you can store it away
early in your main module.
import os, sys
print os.path.abspath(sys.argv[0])
If you need something that is relative to the __file__ attribute of a
module, then again, early in your main module, change sys.path[0] to be
absolute and then all the __file__ attributes will end up absolute. This was
a recent topic of discussion on python-dev. It has been patched for Python
2.3, but the code below will essentially have the same effect.
import sys
sys.path[0] = os.path.abspath(sys.path[0])
Does that solve the problem?
Not entirely (well, it doesn't feel particularly "clean" to me), as it requires that the resource-set be application-specific (every application needs to copy the .zip from every library it uses to it's root (or whatever) directory). Would be really nice to have that inclusion and updating automated. Also doesn't deal with needing the root all over the app/package (i.e. you'd want a module somewhere to do the loading of the .zip).
Example:
wxoo has, at present, 10 icon resources. Those are used all over wxoo and wxprop. Each point in wxoo and wxprop that uses a zipfile-based system needs access to the "root" of the application directory. It then computes the filename root + "wxoo.zip", and your py2exe command then needs to include that .zip in its data-files set.
ConflictSolver (which uses wxoo) has 21 icon resources (at the moment), plus a number of non-icon resources. Again, these resources are used all over the application, and every point a resource is used needs to know how to get to the resource archive for ConflictSolver.
ConflictSolver is normally (during development) run with conflictsolver/ui/application.py . Py2exe makes the result conflictsolver/conflictsolver.exe, so os.path.abspath(sys.path[0]) (root directory) is changing from conflictsolver/ to conflictsolver/ui depending on whether it's the py2exe'd version or not, so you'd want to be able to fix that to not need multiple .zip files.
With resourcepackage, I create the two directories, copy the __init__.py file into them, and can then import the resource modules. When I compose multiple packages, they are all able to access their resources w/out any work in the application that's using them (e.g. don't need to copy the .zip to the application directory). The run-time code has no dependencies on the scanning __init__ mechanism or resourcepackage, it's just modules with raw Python code (or wxPython code, depending on the generators chosen).
The scanning and packaging code for creating and/or updating a zip would
still be useful and that could automatically be called as part of a py2exe
setup.py script. Gordon McMillan's Installer would be a bit trickier since
it uses a .spec file.
Either the zipfile itself could be used as the manifest for the code that
updates all files in the zip or a separate manifest could be used, but using
the zip seems to make the most sense. It just means you have to create the
initial zip with the hierarchy and filenames you want and after that a
simple Python script reads the zip and updates any files that have changed.
...
The problems are all solvable, no question, but as of yet I think I'll stick with python-module-embedding via resourcepackage (I just finished switching wxpypropdist and conflictsolver to it). I'll be happy to switch to zip-mediated versions when it seems more convenient . I'd even be willing to help with it if the approach sounds like it'd be more convenient/reliable than what I've got now.
BTW, if the zip packaging is only called during py2exe, are you including code somewhere to load directly from disk if running w/out py2exe-ing? I'd suggest it's _much_ nicer to have the same mechanism used all the time.
Enjoy,
Mike