Debugging modifications of sys.path
Question: 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?](http://stackoverflow.com/questions/33212466/where-does-sys-path-get-replaced/33212467)


Answer: 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](https://docs.python.org/2/library/site.html) 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(VerboseSysPath, self).insert(*args)
    
        def append(self, *args):
            self.croak('append', args)
            return super(VerboseSysPath, self).append(*args)
    
        def extend(self, *args):
            self.croak('extend', args)
            return super(VerboseSysPath, self).extend(*args)
    
        def pop(self, *args):
            self.croak('pop', args)
            return super(VerboseSysPath, self).pop(*args)
    
        def remove(self, *args):
            self.croak('remove', args)
            return super(VerboseSysPath, self).pop(*args)
    
        def __delitem__(self, *args):
            self.croak('__delitem__', args)
            return super(VerboseSysPath, self).__delitem__(*args)
    
        def __setitem__(self, *args):
            self.croak('__setitem__', args)
            return super(VerboseSysPath, self).__setitem__(*args)
    
        def __setslice__(self, *args):
            self.croak('__setslice__', args)
            return super(VerboseSysPath, self).__setslice__(*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
    

