3

The -s argument to the python interpreter prevents sys.path from having user directories:

-s Don't add user site directory to sys.path.

Setting the PYTHONNOUSERSITE environment variable is another way to achieve the same result. Note that setting a user site directory in PYTHONPATH and then calling a script with -s "overrides" the "user site" removal.

If I do not control how a python script is invoked, is there an easy way to remove user directories in a python script or module? I could iterate over sys.path and remove any entries that start with os.environ["HOME"]. Is that the right way? Will I miss any or maybe remove directories that I shouldn't (e.g., what if someone installed python in their home directory, maybe even in ~/.local/... somewhere?)? Is HOME env var the right thing to look for? I don't see any sys.path.usersite that I can use to seed the path scrubbing effort (but see Update 1).

Is there a way to scrub user site directories that's easier than adding that iteration blob at the top of all the python scripts?

A shebang line like so achieves this:

#!/usr/local/bin/python -s

But if one doesn't want to hard-code the path to the python interpreter, one can use this idiom:

#!/usr/bin/env python

Adding arguments (like -s) to the above doesn't work, however, because of the way shebang lines are interpreted on most unix systems (see Update 2):

env: python -s: No such file or directory

There's two subtle variations to this question:

(1) How to emulate what -s does when your script was not invoked with -s (including allowing user site directories if they are in PYTHONPATH)? Maybe the best way(?) for this variation is:

#!/bin/sh
exec python -s << eof
... python code...
eof

Edit The above fails if you want to pass args. This may work better:

#!/bin/sh
exec python -s - "$@" << "eof"
... python code...
eof

Notice the quoted "eof" to avoid having the shell try to do expansions and substitions in the here document body.

As a side note: that also helps if I want the python -S functionality (which does not have an environment variable knob equivalent) or other python option arguments.

(2) How to emulate -s regardless of PYTHONPATH (i.e., remove user site directories even if they are in PYTHONPATH)?

I guess what I was hoping for was a sys variable that points to the user site dir. But I couldn't find one.

Update 1: Thanks to Blender's comment - the variable is in the site module: site.USER_SITE. So you can iterate over sys.path looking for entries rooted in that directory (could have .egg files in your USER_SITE and to emulate -s, you would need to remove those as well).

Update 2: Using env -S is another solution. It allows you to pass arguments to the command spawned by env(1) in a shebang line. FreeBSD has had -S for years (since 6.0). Linux systems that use coreutils (most) have it as of coreutils 8.30 1. It will take a while for Linux distros to get that version of coreutils, so depending on it for portable scripting is probably not prudent yet (now = 2019).

#!/usr/bin/env -S python -s

p.s. See also this older similar thread.

Juan
  • 1,204
  • 1
  • 11
  • 25
  • 1
    What do you define as a user site directory? Python has `site.USER_SITE`, so you could do `sys.path.remove(site.USER_SITE)`. – Blender Apr 24 '18 at 20:05
  • Thanks. I couldn't find that (I was looking in sys). Note that you may have to remove more than that (to emulate what -s does). Example: if you have a .egg in your USER_SITE dir, that is added to sys.path by default. – Juan Apr 25 '18 at 11:45

0 Answers0