[Python-Dev] Re: Path hacking

Guido van Rossum guido@CNRI.Reston.VA.US
Wed, 15 Sep 1999 18:35:20 -0400


[me]
> > 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.

[JimA]
> 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
> sitecustomize.py.
> 
> > 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[0] 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[0]?  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[0] 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[0] is the absolute pathname of the directory.  You
only see '' if sys.argv[0] doesn't have any pathname information;
that's only possible if the script *does* live in the current
directory.

> > > 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[0] 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/)