Yes, os.py
is the hardcoded landmark.
Modules/getpath.c
#ifndef LANDMARK
#define LANDMARK "os.py"
#endif
z, ? | toggle help (this) |
space, → | next slide |
shift-space, ← | previous slide |
d | toggle debug mode |
## <ret> | go to slide # |
c, t | table of contents (vi) |
f | toggle footer |
r | reload slides |
n | toggle notes |
p | run preshow |
site-packages
directorysite-packages
.site-packages
/usr/lib/python2.6/site-packages/
/usr/lib/python2.6
)site-packages
site.py
at startup.usr/lib/python2.6/site.py
Lib/site.py
in the Python source.site.py
# Prefixes for site-packages;
PREFIXES = [sys.prefix, sys.exec_prefix]
def getsitepackages():
"""Returns a list containing all global site-packages
directories (and possibly site-python).
For each directory present in the global ``PREFIXES``,
this function will find its `site-packages` subdirectory
depending on the system environment, and will return a
list of full paths.
"""
sitepackages = []
seen = set()
for prefix in PREFIXES:
if not prefix or prefix in seen:
continue
seen.add(prefix)
if sys.platform in ('os2emx', 'riscos'):
sitepackages.append(os.path.join(prefix, "Lib", "site-packages"))
elif os.sep == '/':
sitepackages.append(os.path.join(prefix, "lib",
"python" + sys.version[:3],
"site-packages"))
sitepackages.append(os.path.join(prefix, "lib", "site-python"))
else:
sitepackages.append(prefix)
sitepackages.append(os.path.join(prefix, "lib", "site-packages"))
if sys.platform == "darwin":
# for framework builds *only* we add the standard Apple
# locations.
from sysconfig import get_config_var
framework = get_config_var("PYTHONFRAMEWORK")
if framework and "/%s.framework/"%(framework,) in prefix:
sitepackages.append(
os.path.join("/Library", framework,
sys.version[:3], "site-packages"))
return sitepackages
sys.prefix
come from?Python/sysmodule.c
Modules/getpath.c
Modules/getpath.c
#ifndef LANDMARK
#define LANDMARK "os.py"
#endif
static int
search_for_prefix(char *argv0_path, char *home)
{
/* ... */
/* Search from argv0_path, until root is found */
copy_absolute(prefix, argv0_path);
do {
n = strlen(prefix);
joinpath(prefix, lib_python);
joinpath(prefix, LANDMARK);
if (ismodule(prefix))
return 1;
prefix[n] = '\0';
reduce(prefix);
} while (prefix[0]);
sys.prefix
PYTHONHOME
is set, that's sys.prefix
.lib/pythonX.X/os.py
.sys.prefix
.configure --prefix
from build.os.py
is the hardcoded landmark.Modules/getpath.c
#ifndef LANDMARK
#define LANDMARK "os.py"
#endif
$ mkdir scratch; cd scratch
$ mkdir bin
$ cp /usr/bin/python bin/
$ tree
.
`-- bin
`-- python
$ ./bin/python -c "import sys; print(sys.prefix)"
/usr
sys.prefix
is still /usr
.PYTHONHOME
set./home/carljm/scratch/bin/
./home/carljm/scratch/bin/lib/python2.6/os.py
/home/carljm/scratch/lib/python2.6/os.py
/home/carljm/lib/python2.6/os.py
/home/lib/python2.6/os.py
/usr
is the fallback build prefix.$ mkdir -p lib/python2.6
$ touch lib/python2.6/os.py
$ tree
.
|-- bin
| `-- python
`-- lib
`-- python2.6
`-- os.py
$ ./bin/python -c "import sys; print(sys.prefix)"
'import site' failed; use -v for traceback
/home/carljm/scratch
$ ./bin/python -c "import sys; print(sys.path)"
'import site' failed; use -v for traceback
['',
'/home/carljm/scratch/lib/python2.6/',
'/home/carljm/scratch/lib/python2.6/plat-linux2',
'/home/carljm/scratch/lib/python2.6/lib-tk',
'/home/carljm/scratch/lib/python2.6/lib-old',
'/usr/lib/python2.6/lib-dynload']
sys.exec_prefix
$ mkdir lib/python2.6/lib-dynload
$ ./bin/python -c "import sys; print(sys.exec_prefix)"
'import site' failed; use -v for traceback
/home/carljm/scratch
$ ./bin/python -c "import sys; print(sys.path)"
'import site' failed; use -v for traceback
['',
'/home/carljm/scratch/lib/python2.6/',
'/home/carljm/scratch/lib/python2.6/plat-linux2',
'/home/carljm/scratch/lib/python2.6/lib-tk',
'/home/carljm/scratch/lib/python2.6/lib-old',
'/home/carljm/scratch/lib/python2.6/lib-dynload']
site.py
, thus no site-packages
at all.site.py
) into our lib/python2.6
.virtualenv
.orig-prefix.txt
to lib/python2.6
.sys.prefix
.site.py
in lib/python2.6
.site.py
reads orig-prefix.txt
and adds system stdlib paths to
sys.path
.$ tree
.
|-- bin
| `-- python
`-- lib
`-- python2.6
|-- lib-dynload
|-- orig-prefix.txt
|-- os.py
`-- site.py
site.py
def virtual_install_main_packages():
f = open(os.path.join(os.path.dirname(__file__),
'orig-prefix.txt'))
sys.real_prefix = f.read().strip()
# ...
if sys.platform == 'win32':
paths = [os.path.join(sys.real_prefix, 'Lib'),
os.path.join(sys.real_prefix, 'DLLs')]
# ...
else:
paths = [os.path.join(sys.real_prefix,
'lib',
'python'+sys.version[:3])]
# ...
sys.path.extend(paths)
site.py
depends on the standard library!site.py
.site.py
runs, we'll have access to the full stdlib thanks to its
sys.path
additions.virtualenv.py
REQUIRED_MODULES = [
'os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath',
'fnmatch', 'locale', 'encodings', 'codecs',
'stat', 'UserDict', 'readline', 'copy_reg', 'types',
're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile',
'zlib']
def copy_required_modules(dst_prefix):
import imp
for modname in REQUIRED_MODULES:
# ...
try:
f, filename, _ = imp.find_module(modname)
except ImportError:
logger.info("Cannot import bootstrap module: %s" % modname)
else:
if f is not None:
f.close()
dst_filename = change_prefix(filename, dst_prefix)
copyfile(filename, dst_filename)
# ...
site-packages
, if we want it.site.py
def virtual_addsitepackages(known_paths):
# ...
return addsitepackages(known_paths,
sys_prefix=sys.real_prefix)
# ...
def main():
# ...
if GLOBAL_SITE_PACKAGES:
paths_in_sys = virtual_addsitepackages(paths_in_sys)
# ...
site.py
.bin/activate
?bin/
to the front of your shell PATH
.import sys
sys.path.insert(0,
"/path/to/venv/lib/python2.6/site-packages")
import site
site.addsitedir(
"/path/to/venv/lib/python2.6/site-packages")
execfile("/path/to/venv/bin/activate_this.py")
site.py
.site.py
(e.g. Debian dist-packages
).site.py
.https://bitbucket.org/brandon/virtualenv-small-sitepy
site.py
a light wrapper around the system site.py
.https://github.com/kvbik/rvirtualenv
PYTHONHOME
!sys.prefix
with no copied binary.site.py
hacks.pip/req.py
def install(self, install_options, global_options=()):
# ...
install_args = [
sys.executable, '-c',
"import setuptools;__file__=%r;"\
"execfile(__file__)" % self.setup_py] +\
list(global_options) + [
'install',
'--single-version-externally-managed',
'--record', record_filename]
# ...
call_subprocess(install_args + install_options,
cwd=self.source_dir,
filter_stdout=self._filter_install,
show_stdout=False)
python -c
"import setuptools;__file__=/p/to/setup.py;execfile(__file__)"
install
--single-version-externally-managed
--record /tmp/pip-ZgGVWG-record/install-record.txt
"import setuptools;__file__=/p/to/setup.py;execfile(__file__)"
install
python setup.py install
.--single-version-externally-managed
Tells setuptools to do a "flat" (distutils-style) install and put the
metadata next to it in a .egg-info
directory, rather than a zipped egg or
egg-directory.
A setuptools feature.
$ easy_install yolk
# cd to site-packages
$ ls | egrep "(yolk|easy)"
easy-install.pth
yolk-0.4.1-py2.6.egg
$ cat easy-install.pth
./setuptools-0.6c11-py2.6.egg
./pip-0.8.1-py2.6.egg
./yolk-0.4.1-py2.6.egg
import sys; new=sys.path[sys.__plen:]; del sys.path[sys.__plen:]; p=getattr(sys,'__egginsert',0); sys.path[p:p]=new; sys.__egginsert = p+len(new)
--single-version-externally-managed
:$ pip install yolk
$ ls | grep yolk
yolk/
yolk-0.4.1-py2.6.egg-info/
--record /tmp/pip-ZgGVWG-record/install-record.txt
installed-files.txt
in the .egg-info
metadata directory.pip
as an APIpip/commands/install.py
class InstallCommand(Command):
name = 'install'
usage = '%prog [OPTIONS] PACKAGE_NAMES...'
summary = 'Install packages'
bundle = False
def __init__(self):
super(InstallCommand, self).__init__()
self.parser.add_option(
'-e', '--editable',
dest='editables',
action='append',
default=[],
metavar='VCS+REPOS_URL[@REV]#egg=PACKAGE',
# ...
def run(self, options, args):
# ...
from pip.req import InstallRequirement, RequirementSet
from pip.index import PackageFinder
from pip.locations import build_prefix, src_prefix
reqset = RequirementSet(build_dir=build_prefix,
src_dir=src_prefix,
download_dir=None)
req = InstallRequirement.from_line("yolk==0.4.1",
comes_from=None)
reqset.add_requirement(req)
finder = PackageFinder(
find_links=[],
index_urls=["http://pypi.python.org/simple"])
reqset.prepare_files(finder)
reqset.install(install_options=[], global_options=[])
reqset.cleanup_files()
#pip
on Freenode