Python searches the paths in sys.path in order (see http://docs.python.org/tutorial/modules.html#the-module-search-path). easy_install changes this list directly (see the last line in your easy-install.pth file):

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)

This basically takes whatever directories are added and inserts them at the beginning of the list.

Also see Eggs in path before PYTHONPATH environment variable.

Answer from cwa on Stack Overflow
Top answer
1 of 4
25

Python searches the paths in sys.path in order (see http://docs.python.org/tutorial/modules.html#the-module-search-path). easy_install changes this list directly (see the last line in your easy-install.pth file):

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)

This basically takes whatever directories are added and inserts them at the beginning of the list.

Also see Eggs in path before PYTHONPATH environment variable.

2 of 4
21

This page is a high Google result for "Python import order", so here's a hopefully clearer explanation:

  • https://docs.python.org/library/sys.html#sys.path
  • https://docs.python.org/tutorial/modules.html#the-module-search-path

As both of those pages explain, the import order is:

  1. Built-in python modules. You can see the list in the variable sys.modules.
  2. The sys.path entries.
  3. The installation-dependent default locations.

And as the sys.path doc page explains, it is populated as follows:

  1. The first entry is the FULL PATH TO THE DIRECTORY of the file which python was started with (so /someplace/on/disk/> $ python /path/to/the/run.py means the first path is /path/to/the/, and likewise the path would be the same if you're in /path/to/> $ python the/run.py (it is still ALWAYS going to be set to the FULL PATH to the directory no matter if you gave python a relative or absolute file)), or it will be an empty string if python was started without a file aka interactive mode (an empty string means "current working directory for the python process"). In other words, Python assumes that the file you started wants to be able to do relative imports of package/-folders and blah.py modules that exist within the same location as the file you started python with.
  2. The other entries in sys.path are populated from the PYTHONPATH environment variable. Basically your global pip folders where your third-party python packages are installed (things like requests and numpy and tensorflow).

So, basically: Yes, you can trust that Python will find your local package-folders and module files first, before any globally installed pip stuff.

Here's an example to explain further:

myproject/ # <-- This is not a package (no __init__.py file).
  modules/ # <-- This is a package (has an __init__.py file).
    __init__.py
    foo.py
  run.py
  second.py

executed with: python /path/to/the/myproject/run.py
will cause sys.path[0] to be "/path/to/the/myproject/"

run.py contents:
import modules.foo as foo # will import "/path/to/the/myproject/" + "modules/foo.py"
import second # will import "/path/to/the/myproject/" + "second.py"

second.py contents:
import modules.foo as foo # will import "/path/to/the/myproject/" + "modules/foo.py"

EDIT:

You can run the following command to print a sorted list of all built-in module names. These are the things that load before ANY custom files/module folders in your projects. Basically these are names you must avoid in your own custom files:

python -c "import sys, json; print(json.dumps(sorted(list(sys.modules.keys())), indent=4))"

List as of Python 3.9.0:

"__main__",
"_abc",
"_bootlocale",
"_codecs",
"_collections",
"_collections_abc",
"_frozen_importlib",
"_frozen_importlib_external",
"_functools",
"_heapq",
"_imp",
"_io",
"_json",
"_locale",
"_operator",
"_signal",
"_sitebuiltins",
"_sre",
"_stat",
"_thread",
"_warnings",
"_weakref",
"abc",
"builtins",
"codecs",
"collections",
"copyreg",
"encodings",
"encodings.aliases",
"encodings.cp1252",
"encodings.latin_1",
"encodings.utf_8",
"enum",
"functools",
"genericpath",
"heapq",
"io",
"itertools",
"json",
"json.decoder",
"json.encoder",
"json.scanner",
"keyword",
"marshal",
"nt",
"ntpath",
"operator",
"os",
"os.path",
"pywin32_bootstrap",
"re",
"reprlib",
"site",
"sre_compile",
"sre_constants",
"sre_parse",
"stat",
"sys",
"time",
"types",
"winreg",
"zipimport"

So NEVER use any of those names for you .py files or your project module subfolders.

🌐
Note.nkmk.me
note.nkmk.me › home › python
Check and Add the Module Search Path in Python: sys.path | note.nkmk.me
May 12, 2023 - cd .. pwd # /Users/mbp/Documents/my-project/python-snippets python3 notebook/print_sys_path.py # ['/Users/mbp/Documents/my-project/python-snippets/notebook', # '/Users/mbp/Documents/lib', # '/Users/mbp/Documents/my-project/python-snippets', # '/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python37.zip', # '/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7', # '/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload', # '/usr/local/lib/python3.7/site-packages'] ... Since the module search path changes depending on the current directory, the import may fail depending on where the script file is executed. Modules are searched in the order listed in sys.path.
🌐
Quora
quora.com › How-is-the-Python-SYS-path-set
How is the Python SYS path set? - Quora
Answer (1 of 3): sys.path is set in order as : 1. The current directory 2. Directories derived from the PYTHONPATH environment variable if set 3. Standard installation directories for this version of Python (for instance [code ]/usr/lib/python . )[/code] - these tend to be the python runtime...
🌐
Python
docs.python.org › 3 › library › sys_path_init.html
The initialization of the sys.path module search path — Python 3.15.2 documentation
To completely override sys.path create a ._pth file with the same name as the shared library or executable (python._pth or python311._pth). The shared library path is always known on Windows, however it may not be available on other platforms. In the ._pth file specify one line for each path to add to sys.path.
🌐
GitHub
github.com › pypa › setuptools › issues › 686
Difference in sys.path order, depending on how run · Issue #686 · pypa/setuptools
August 24, 2016 - The actual diff of sys.path for the two environments is: "path": [ "/private/var/folders/j2/gr3cj3jn63s5q8g3bjvw57hm0000gp/T/test_cover_52005401", "/Users/ned/coverage/trunk/tests/modules", "/Users/ned/coverage/trunk/tests/zipmods.zip", "/Users/ned/coverage/trunk/.tox/py27/lib/python27.zip", "/Users/ned/coverage/trunk/.tox/py27/lib/python2.7", "/Users/ned/coverage/trunk/.tox/py27/lib/python2.7/plat-darwin", "/Users/ned/coverage/trunk/.tox/py27/lib/python2.7/plat-mac", "/Users/ned/coverage/trunk/.tox/py27/lib/python2.7/plat-mac/lib-scriptpackages", "/Users/ned/coverage/trunk/.tox/py27/lib/pytho
Author: pypa
🌐
Thomas Stringer
trstringer.com › python-module-import-precedence
Module Import Precedence in Python | Thomas Stringer
May 12, 2017 - The first element of sys.path will be the current directory of the module that is running the import. In my case, that directory is ./module_import_test/. If Python doesn’t find the module in the local directory, it’ll then move onto the paths specified in $PYTHONPATH.
🌐
Python.org
discuss.python.org › ideas
PYTHONPATH priority after standard library? - Ideas - Discussions on Python.org
November 11, 2020 - Would it be appropriate/acceptable to put sys.path inserts such as PYTHONPATH and/or '' when that is added at a lower priority than the standard library, instead of always top priority? This is related to Python flag/envvar not to put current directory to sys.path (but don't ignore PYTHONPATH) (and several of the historical links in this comment) in that it involves the behavior of PYTHONPATH and/or current directory (when that happens) being added to the front of sys.path, but I haven’t seen t...
Top answer
1 of 2
9

As you may know, sys.path is initialized from:

  • the current directory
  • your PYTHONPATH
  • an installation-dependent default

However unfortunately that is only part of the story: setuptools creates easy-install.pth files, which also modify sys.path and worst of all they prepend packages and therefore totally mess up the order of directories.

In particular (at least on my system), there is /usr/local/lib/python2.7/dist-packages/easy-install.pth with the following contents:

import sys; sys.__plen = len(sys.path)
/usr/lib/python2.7/dist-packages
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)

This causes /usr/lib/python2.7/dist-packages to be prepended even before your PYTHONPATH!

What you could do is simply change the 2nd line in this file to

/usr/local/lib/python2.7/dist-packages

and you will get your desired priority.

However beware this file might be overwritten or changed again by a future setuptools invocation!

2 of 2
2

We encountered an almost identical situation and wanted to expand upon @kynan's response which is spot-on. In the case where you have such an easy-install.pth that you want to overcome, but which you cannot modify it (say you are a user with no root/admin access), you can do the following:

  • Set up an alternate python installation scheme

    • e.g. we use a PYTHON HOME install (setting PYTHONUSERBASE)
  • Create a user/home site-packages

    • You can do this by installing a package into the user env: pip install <package> --user
  • Create a pth to set sys.__egginsert to workaround the system/distribution easy-install.pth

    • Create a $PYTHONUSERBASE/lib/python2.7/site-packages/fix_easy_install.pth
    • Containing: import sys; sys.__egginsert = len(sys.path);

This will set sys.__egginsert to point to the end of your sys.path including your usersite paths. When the nefarious system/dist easy-install.pth will then insert its items at the end of the system path.

🌐
Stack Overflow
stackoverflow.com › questions › 14882377 › is-the-order-reported-by-sys-path-the-order-in-which-packages-are-searched
python - Is the order reported by 'sys.path' the order in which packages are searched? - Stack Overflow
>>> from pprint import pprint >>> pprint(sys.path) ['', '/Library/Python/2.7/site-packages/ipython-0.14.dev-py2.7.egg', '/Library/Python/2.7/site-packages/matplotlib-1.3.x-py2.7-macosx-10.8-intel.egg', '/Library/Python/2.7/site-packages/numpy-1.8.0.dev_3abd869_20121222-py2.7-macosx-10.8-intel.egg', '/Library/Python/2.7/site-packages/pymc-2.2-py2.7-macosx-10.8-intel.egg', '/Library/Python/2.7/site-packages/scikit_learn-0.13_git-py2.7-macosx-10.8-intel.egg', '/Library/Python/2.7/site-packages/scipy-0.12.0.dev_d631749_20121222-py2.7-macosx-10.8-intel.egg', '/Library/Python/2.7/site-packages/stats
Find elsewhere
🌐
Python
mail.python.org › pipermail › tutor › 2010-April › 075769.html
[Tutor] sys.path and the path order
April 23, 2010 - Notice that the script directory is inserted before the entries inserted as a result of PYTHONPATH. http://docs.python.org/library/sys.html#sys.path So the answer to your question is, Yes. -- Steven D'Aprano · Previous message: [Tutor] sys.path and the path order ·
🌐
PyTutorial
pytutorial.com › python-path-management-pythonpath-and-syspath
PyTutorial | Python Path Management: PYTHONPATH and sys.path
May 10, 2025 - For advanced import techniques, see Python Import System Guide. Proper path management is crucial for Python imports. Use PYTHONPATH for system-wide changes and sys.path for runtime adjustments.
🌐
LabEx
labex.io › tutorials › python-how-to-check-the-python-system-path-to-find-necessary-modules-397953
How to check the Python system path to find necessary modules | LabEx
The order of the directories in the list is important, as Python will search the directories in the order they appear in the list. For example, if you have a custom module located in the /path/to/my/module directory, and you want to import that ...
🌐
pytest
docs.pytest.org › en › 7.1.x › explanation › pythonpath.html
pytest import mechanisms and sys.path/PYTHONPATH — pytest documentation
The pythonpath configuration variable. Here’s a list of scenarios when using prepend or append import modes where pytest needs to change sys.path in order to import test modules or conftest.py files, and the issues users might encounter because of that.
🌐
Devgex
devgex.com › en › article › 00019311
Understanding Python Module Search Path: A Comprehensive Guide to sys.path and PYTHONPATH - DevGex
November 22, 2025 - Python searches directories in the order they appear in sys.path, stopping at the first location where the requested module is found.
🌐
Linux Hint
linuxhint.com › sys-path-append-python
How to Use Sys.path.append() in Python – Linux Hint
... What you notice here is that first of all, it’s a list. So according to the list, it will first look in the current working directory, then in other directories one by one. The current working directory is the directory in which the main python script – the one being executed – is found.
Top answer
1 of 2
96

I'm quite a beginner in Python and I found the answer of Anand was very good but quite complicated to me, so I try to reformulate :

1) insert and append methods are not specific to sys.path and as in other languages they add an item into a list or array and :
* append(item) add item to the end of the list,
* insert(n, item) inserts the item at the nth position in the list (0 at the beginning, 1 after the first element, etc ...).

2) As Anand said, python search the import files in each directory of the path in the order of the path, so :
* If you have no file name collisions, the order of the path has no impact,
* If you look after a function already defined in the path and you use append to add your path, you will not get your function but the predefined one.

But I think that it is better to use append and not insert to not overload the standard behaviour of Python, and use non-ambiguous names for your files and methods.

2 of 2
65

Because Python checks in the directories in sequential order, starting at the first directory in the sys.path list, until it finds the .py file it was looking for.

Normally, the current directory or the directory of the script is the first element in the list, unless you modify it (like you did). From documentation:

As initialized upon program startup, the first item of this list, path[0], is the directory containing the script that was used to invoke the Python interpreter. If the script directory is not available (e.g. if the interpreter is invoked interactively or if the script is read from standard input), path[0] is the empty string, which directs Python to search modules in the current directory first. Notice that the script directory is inserted before the entries inserted as a result of PYTHONPATH.

So, most probably, you had a .py file with the same name as the module you were trying to import from, in the current directory (where the script was being run from).

Also, something to note about ImportErrors - Let's say the import error says: ImportError: No module named main. This doesn't mean main.py is overwritten - if it was overwritten it would still exist and we would not have issues trying to read it. It's some module above this that got overwritten with a .py or some other file.

For example, consider a directory structure that looks like this:

 - test
    - shared
       - __init__.py
       - phtest.py
    - testmain.py

Now from testmain.py, I call from shared import phtest, which works fine.

Now let's say I introduce a shared.py in test directory:

 - test
    - shared
       - __init__.py
       - phtest.py
    - testmain.py 
    - shared.py

Now when I try to do from shared import phtest from testmain.py, I get the error:

ImportError: cannot import name 'phtest'

As you can see above, the file that introduced the issue is shared.py, not phtest.py.

🌐
O'Reilly
oreilly.com › library › view › python-cookbook › 0596001673 › ch04s23.html
Dynamically Changing the Python Search Path - Python Cookbook [Book]
July 19, 2002 - Windows is case-insensitive, so lowercase # for definiteness. new_path = os.path.abspath(new_path) if sys.platform == 'win32': new_path = new_path.lower( ) # Check against all currently available paths for x in sys.path: x = os.path.abspath(x) if sys.platform == 'win32': x = x.lower( ) if new_path in (x, x + os.sep): return 0 sys.path.append(new_path) return 1 if _ _name_ _ == '_ _main_ _': # Test and show usage import sys print 'Before:' for x in sys.path: print x if sys.platform == 'win32': print AddSysPath('c:\\Temp') print AddSysPath('c:\\temp') else: print AddSysPath('usr/lib/my_modules') print 'After:' for x in sys.path: print x · Modules must be on the Python search path before they can be imported, but we don’t want to have a huge permanent path, ...
Authors: Alex MartelliDavid Ascher
Published: 2002
Pages: 608
🌐
IT trip
en.ittrip.xyz › python
Comprehensive Guide to Understanding and Efficiently Using sys.path in Python | IT trip
October 22, 2024 - This list includes directories ... variable, and the current directory. When a module is imported, Python searches these directories in order and imports the first module it finds....