pythonpython-3.xpython-importsite-packages

How does Python know to import from the code i'm working on, rather than importing from site-packages?


Background

I have a package i'm working on which i have also installed into site-packages. (I've installed my own package using pip)

Question

How does Python know to import from the "local" code (the code i'm working on), rather than importing from site-packages? I'm asking because i want to better understand and i'm worried that somehow i might import code from site-packages when i really want to use my own (latest) code

It’s confusing to me that this is not more clear in how we write imports. It seems to me that the programmer doesn’t know if she is importing her own code or importing from site-packages. Am i missing something here?


One thought i had was to use relative imports but if i understand they are not recommended in general


I'm using Python 3.8.5


Solution

  • Python's import mechanism (commonly referred as the import machinery) is based on Finders and Loaders. When you import a module using the import statement, a series are finders try to find the module that you are importing. You can see the list of all finders that are triggered in order by:

    >>> import sys
    >>> sys.meta_path
    [<class '_frozen_importlib.BuiltinImporter'>,
     <class '_frozen_importlib.FrozenImporter'>,
     <class '_frozen_importlib_external.PathFinder'>]
    

    If none of the finders are able to resolve the module, then ModuleNotFoundError is raised.

    BuiltinImporter resolves modules like sys, time, gc etc which are preloaded into the interpreter. FrozenImporter resolves frozen modules. PathFinder resolves modules by going through the paths in sys.path.

    Printing sys.path shows that your current directory is the first entry and hence is searched for a match first.

    Here's a simple sequence you can use to reason about where the import is going to happen from:

    1. Is the module part of built-in modules. Example: import sys. Even if you have a file named sys.py in your current directory, since BuiltinImporter is called first, it will resolve the built-in sys module.
    2. Is the module present in your current directory, since that is the first entry in sys.path.
    3. Is the module available as part of core python or site-packages.

    Modules that are imported by PathFinder (ones present in sys.path) will have __path__ as an attribute that you can check to see where it is located.

    It is also possible to reorder the finders in sys.meta_path or even add your own custom finders and loaders giving you full control and creativity to modify the default machinery. Custom finders and loaders can be registered to look for modules elsewhere in the system or even dynamically from external systems.