[Distutils] setuptools-0.4a2: Eggs, scripts, and __file__

Phillip J. Eby pje at telecommunity.com
Mon Jun 13 07:15:38 CEST 2005


At 12:16 AM 6/13/2005 -0400, Ryan Tomayko wrote:
> From "[Distutils] A plan for scripts (in EasyInstall)"
><http://mail.python.org/pipermail/distutils-sig/2005-June/004594.html>
>
>On Mon Jun 6 16:44:19 CEST 2005, Phillip J. Eby wrote:
> > The 'run_main' function would do several things:
><snip>
> >
> >   * Clear everything but __name__ from the __main__ namespace
><snip>
> >   * exec the script in __main__, using something like:
> >
> >      maindict['__file__'] = pseudo_filename code =
> >      compile(script_source, pseudo_filename, "exec") exec code in
> >      maindict, maindict
>
>It seems that bullet one is happening but not bullet two? I have
>scripts that are attempting to use __file__ but failing with:
>
>     NameError: name '__file__' is not defined

I'll fix this in the next release.


>The script looks like it would work properly if it was given a pseudo
>filename but this has me thinking about what the best way to detect
>development environments in scripts will look like in an eggified
>environment.

That's the wrong question to ask, IMO.  Think about how to make the script 
work exactly the same in all environments, instead.  :)


>My wrapper scripts generally look something like the
>following to detect whether the script is being run from a
>development location or a deployed location::
>
>     import sys
>     from os.path import dirname, abspath, join, exists
>     devel_dir = dirname(dirname(abspath(__file__)))
>     if exists(join(devel_dir, 'support')):
>          sys.path.insert(1, join(devel_dir, 'support'))
>          sys.path.insert(1, devel_dir)
>     from package.module import main
>     main(sys.argv)
>
>Assuming a directory layout of:
>
>     [devel-dir]/bin (scripts in here)
>     [devel-dir]/support (packages/modules)
>     [devel-dir]/[package-name]

Have you read this:

http://peak.telecommunity.com/DevCenter/PythonEggs#developing-with-eggs

The complexity you're incurring here is unnecessary; between require() and 
.pth files you should never need to mess with sys.path manually.


>At first I thought I should switch from using path operations on
>__file__ to using `pkg_resources.resource_isdir` and
>`resource_filename` but that doesn't make any sense - if the script
>is running from within a deployed egg, I'm not using it from a
>development environment

Not true; see the link above.  When you do development from your distutils 
package root, your development code *is* in an egg.  However, you still 
shouldn't be checking __file__ or fiddling with sys.path, and there is no 
need anyway.  Here's one idea of what your tree could look like:

devel_dir/
     some_dependency-1.2.egg
     otherpackage-3.9-whatever.egg

     package_you_are_working_on/
         __init__.py
         some_module.py

     somescript.py

     MyPackage.egg-info/   <- this makes devel_dir a "source egg" for MyPackage
     setup.py

     build/
     dist/
         MyPackage-1.1.egg  <- built egg; not actually used for development


You'll notice that everything is just thrown into the same directory; if 
you use this setup for development, everything will "just work".

So, you create a setup.py for your package, and you run setup.py bdist_egg; 
this will dump an egg in dist/, and create MyPackage.egg-info, marking 
devel_dir as a "development egg".

Install any other packages you need to the current directory using 
'easy_install -xd. package_you_need' (the -x excludes their scripts).  Now 
you're ready to party.  Make your scripts use 'require()' to ask for 
'MyPackage'; when you run them (whether you are in the devel_dir or not), 
they will find MyPackage.egg-info, find the dependencies declared, and add 
all the needed .eggs to sys.path automatically.

This is just *one* layout that works.  The dependency eggs don't have to be 
in devel_dir; they can be anywhere that will already be on sys.path, like 
site-packages or a directory named in a .pth file in site-packages.

Does this explain it better?  One side benefit of egg-based installation is 
that you can dump as many libraries in site-packages as you want and not 
worry about version conflicts, so it's definitely how I plan to do most 
development.  The directory where a script is located, however, takes 
precedence over site-packages, which means that even if you have the 
package you're developing already installed in site-packages, your 
development egg will take precedence if the script you're running is in 
that directory.


>  and the resource_*** functions don't make
>sense in __main__ context anyway. So my current thinking is that the
>existing idiom should remain and that a pseudo filename shouldn't
>pose any problems in the scenarios I'm dealing with:
>
>  * Deployed egg: don't tamper with sys.path
>  * Deployed site-packages: don't tamper with sys.path
>  * Development environment: insert development paths

You should be able to make that last one work the same way; i.e., without 
tampering with sys.path.  If you can't, please explain your situation 
further, because I want pkg_resources to be able to prevent all future 
sys.path munging by anything but EasyInstall itself, and by extensible 
applications that have to manage plugin directories.



More information about the Distutils-SIG mailing list