Background: I have a small Python application that makes life for developers releasing software in our company a bit easier. I build an executable for Windows using py2exe. The application as well as the binary are checked into Subversion. Distribution happens by people just checking out the directory from SVN. The program has about 6 different Python library dependencies (e.g. ElementTree, Mako)
The situation: Developers want to hack on the source of this tool and then run it without having to build the binary. Currently this means that they need a python 2.6 interpreter (which is fine) and also have the 6 libraries installed locally using easy_install.
The Problem
This is not a public, classical open source environment: I'm inside a corporate network, the tool will never leave the "walled garden" and we have seriously inconvenient barriers to getting to the outside internet (NTLM authenticating proxies and/or machines without direct internet access).
I want the hurdles to starting to hack on this tool to be minimal: nobody should have to hunt for the right dependency in the right version, they should have to execute as little setup as possible. Optimally the prerequisites would be having a Python installation and just checking out the program from Subversion.
Anecdote: The more self-contained the process is the easier it is to repeat it. I had my machine swapped out for a new one and went through the unpleasant process of having to reverse engineer the dependencies, reinstall distutils, hunting down the libraries online and getting them to install (see corporate internet restrictions above).
解决方案
I sometimes use the approach I describe below, for the exact same reason that @Boris states: I would prefer that the use of some code is as easy as a) svn checkout/update - b) go.
But for the record:
I use virtualenv/easy_install most of the time.
I agree to a certain extent to the critisisms by @Ali A and @S.Lott
Anyway, the approach I use depends on modifying sys.path, and works like this:
Require python and setuptools (to enable loading code from eggs) on all computers that will use your software.
Organize your directory structure this:
project/
*.py
scriptcustomize.py
file.pth
thirdparty/
eggs/
mako-vNNN.egg
... .egg
code/
elementtree\
*.py
...
In your top-level script(s) include the following code at the top:
from scriptcustomize import apply_pth_files
apply_pth_files(__file__)
Add scriptcustomize.py to your project folder:
import os
from glob import glob
import fileinput
import sys
def apply_pth_files(scriptfilename, at_beginning=False):
"""At the top of your script:
from scriptcustomize import apply_pth_files
apply_pth_files(__file__)
"""
directory = os.path.dirname(scriptfilename)
files = glob(os.path.join(directory, '*.pth'))
if not files:
return
for line in fileinput.input(files):
line = line.strip()
if line and line[0] != '#':
path = os.path.join(directory, line)
if at_beginning:
sys.path.insert(0, path)
else:
sys.path.append(path)
Add one or more *.pth file(s) to your project folder. On each line, put a reference to a directory with packages. For instance:
# contents of *.pth file
thirdparty/code
thirdparty/eggs/mako-vNNN.egg
I "kind-of" like this approach. What I like: it is similar to how *.pth files work, but for individual programs instead of your entire site-packages. What I do not like: having to add the two lines at the beginning of the top-level scripts.
Again: I use virtualenv most of the time. But I tend to use virtualenv for projects where I have tight control of the deployment scenario. In cases where I do not have tight control, I tend to use the approach I describe above. It makes it really easy to package a project as a zip and have the end user "install" it (by unzipping).