[Python-Dev] Re: Path hacking
Guido van Rossum
Wed, 15 Sep 1999 18:35:20 -0400
> > But the intention here is for the customization to be application
> > specific (hence the Spam in the name). sitecustomize doesn't know
> > whethere I need the Mailman or the Knowbot root added to my path.
> Ah, you have multiple scripts in one directory and multiple
> Foo_path, Bar_path etc. I was thinking with my Windows head.
> A commercial Windows app generally has its own exclusive
> install directory, so I was thinking single directory so a single
> > Or do you mean to imply that we can do this with zero text added to
> > the script, by simply dropping an appropriate sitecustomize.py in the
> > script dir?
> Yes, that is exactly what I was thinking.
> > Unfortunately this does currently *not* work, because
> > sys.path is added after Py_Initialize() is run.
> Yikes! That kills using sitecustomize.py. Your Spam_path
> still works because it is imported later, but requires an
> import in each Python main script just as you said.
Not too bad (who cares about one more line of boilerplate...).
> Even worse, it means that exceptions.py and site.py can not
> be found at all except using the normal PYTHONPATH, and
> putting their path in Spam_path will *not* work.
Why would you want your own exceptions.py and site.py?
> > > > Because the script's directory is first on the default path, the Spam
> > > > scripts will pick up Spam_path without any help from $PYTHONPATH.
> > >
> > > Hmmm. Is this really true? Nothing else, for example the registry, can
> > > change sys.path? Ever? Please say yes.
> > Yes. (The registry can add module-specific paths, which will be
> > searched before sys.path is even looked at, but this is only for
> > specific modules. It cannot insert a general directory that is
> > searched.) The only way this can fail is if an embedding app fails to
> > call PySys_SetArgv().
> Oh dear, I think I heard no instead of yes. Are you saying that if
> someone else installs a Python app on my customer's machine after I do,
> and sets a registry entry which sayes to use c:/other/path/to/site.py
> for site.py (as he may very well want to do), then if my Python program
> depends on getting my copy of site.py from my directory, it will then
> use the other copy instead and may very well fail?
Again - why would anyone register their own site.py?
> > In any case, that's a separate issue -- I
> > agree that if sys.path is '' (as it often is) it's better for
> > site.py or sitecustomize.py or Spam_path.py (or whoever) to absolutize
> > it (and everything else on the path) so that it will still work if the
> > app does a chdir().
> Point on the curve: Windows apps generally start from an icon
> which contains their path and current working directory, and
> these are generally different. So a Windows app in general will
> *never* have had a getcwd() equal to the path of either the
> binary interpreter or the Python main script.
You're lucky. It turns out that on Windows, under those circumstances
at least, sys.path is the absolute pathname of the directory. You
only see '' if sys.argv doesn't have any pathname information;
that's only possible if the script *does* live in the current
> > > The files exceptions.py and site.py must be in all the bin
> > > directories as well as sitecustomize.py because they are
> > > automatically imported in Py_Initialize().
> > Yes.
> Well, *no* right? This fails unless the bin directories are in
> fact on PYTHONPATH. The only way to get exceptions.py is by using
> sys.path as it exists within Py_Initialize(). So there is no
> hacked sys.path equal to the script dir. And since the
> path hacks in site.py haven't happened yet either, we have
> an incomplete sys.path at that point.
Sorry, I've lost track of what we were after here. Indeed the
scripts' directory (which I presume you meant by the bin directory)
indeed doesn't occur in sys.path until after Py_Initialize() has run.
> > > added to sys). How about prepending the single directory sys.executable
> > > to sys.path during Py_Initialize()? And demanding that modules
> > > like the new Greg_importer.py[c], exceptions.py[c] and site.py[c]
> > > be placed there.
> > On Unix, this is a bin directory and it is strongly discouraged to put
> > non-program files there.
> Ok, point taken.
> > Is the full DLL path available at any point? This would certainly be
> > a good starting point -- especially when the DLL is loaded implicitly
> > as the result of some COM operation.
> I don't know about loading by COM, but if it is a file, its absolute
> path is reliably known in sys, the code is identical to that currently
> used for sys.executable (on Windows), and I have a patch if you want.
I presume using GetModuleFileName()? Please send me the patch!
> JimA's conjecture: It is currently impossible to
> ship a Python app which can not be damaged by the installation of a
> second Python app without using a hacked custom binary.
Sounds right. All tricks to make the app unique require using a
different registry key, which requires a change to the DLL. However,
you can do this without recompiling! The version string is used is
embedded in a resource, so you can patch it using some kind of
resource editor. Mark Hammond planned it this way!
--Guido van Rossum (home page: http://www.python.org/~guido/)