Debugging modifications of sys.path

Some library seems to modify my sys.path, although I don't want ìt to be changed.

How can I find the python code line which alters sys.path?

Related

  • Where does sys.path get replaced?

Solution 1:

One of the first things imported is the sitecustomize and usercustomize modules; you could replace sys.path with a custom list implementation that records all changes being made.

First, find where to place a usercustomize or sitecustomize module; the site module can tell you where to place the first:

python -m site --user-site

If that directory doesn't exist yet, create it and in it put a usercustomize.py with:

import sys

class VerboseSysPath(list):
    def croak(self, action, args):
        frame = sys._getframe(2)
        print('sys.path.{}{} from {}:{}'.format(
            action, args, frame.f_code.co_filename, frame.f_lineno))

    def insert(self, *args):
        self.croak('insert', args)
        return super().insert(*args)
    
    def append(self, *args):
        self.croak('append', args)
        return super().append(*args)

    def extend(self, *args):
        self.croak('extend', args)
        return super().extend(*args)

    def pop(self, *args):
        self.croak('pop', args)
        return super().pop(*args)

    def remove(self, *args):
        self.croak('remove', args)
        return super().remove(*args)

    def __delitem__(self, *args):
        self.croak('__delitem__', args)
        return super().__delitem__(*args)

    def __setitem__(self, *args):
        self.croak('__setitem__', args)
        return super().__setitem__(*args)

sys.path = VerboseSysPath(sys.path)

This now will complain about all attempts at altering the sys.path list.

Demo, with the above placed in either the site-packages/sitecustomize.py or `python -m site --user-site`/usercustomize.py modules:

$ cat test.py 
import sys

sys.path.append('')
$ bin/python test.py 
sys.path.append('',) from test.py:3

Solution 2:

Starting python with python -S causes python not to load site.py, and so its default value is preserved from when python first starts up.