Skip to content

Instantly share code, notes, and snippets.

@twolfson
Last active October 23, 2025 10:25
Show Gist options
  • Select an option

  • Save twolfson/7636887 to your computer and use it in GitHub Desktop.

Select an option

Save twolfson/7636887 to your computer and use it in GitHub Desktop.
How Python modules are resolved

Python modules have 2 syntaxes for importing.

import x
from x import y

import x

Absolute imports are used for importing top-level modules and only top level modules. These are ones that are globally installed, either inside of Python core or via a package manager (e.g. pip).

import json  # Python core
import yaml  # Installed via `pip install pyyaml`

When you declare a global import, Python looks for the __init__.py of a top-level module. When you are working inside of a virtual environment, this is

~/.virtualenvs/<your_virtualenv>/lib/python2.7/site-packages/<package_name>/__init__.py

If this file is populated, it will return all variables declared at the top scope.

# hello/__init__.py

# This file returns `a` and `c` when imported
a = 'b'
def c():
  d = 'e'

Python 2 note

THIS SECTION SHOULD BE AVOIDED IF YOU ARE TRYING TO DEVELOP CROSS-VERSION MODULES

Inside Python 2, import x can resolve local files as modules. There are 2 cases:

world/__init__.py

If a folder is named the same as the top level module, an __init__.py is looked for. If that exists, then we will follow the same variable procedure as an absolute module (if empty, collect from sibling files. otherwise, return exposed variables.)

hello/
    hello.py # `import world`
    world/
        __init__.py # first looks for this

# If not found, looks here
~/.virtualenvs/<your_virtualenv>/lib/python2.7/site-packages/world/__init__.py

world.py

If a file is named the same as the top level module, the local file's contents will be returned.

hello/
    hello.py # `import world`
    world.py # first looks for this

# If not found, looks here
~/.virtualenvs/<your_virtualenv>/lib/python2.7/site-packages/world/__init__.py

Order

The order that these cases are dealt with is folder -> file -> top-level

hello/
    hello.py # `import world`
    world/
        __init__.py # first looks for this
    world.py # second looks here

# If not found, looks here
~/.virtualenvs/<your_virtualenv>/lib/python2.7/site-packages/world/__init__.py

from x import y

Requests for absolute modules are returned the exact same between from x import y and import x. The difference is that the items returned as only those in the import y piece.

# hello/__init__.py

# `from hello import a` will return `a` as a variable
a = 'b'
def c():
  d = 'e'

In addition to this, Python 2.5+ and 3 support relative imports.

# Inside of hello/hello.py
from .world import status

When resolving a relative module, Python first looks for a folder with that name and its __init__.py. If that exists, it will extract the variable from the __init__.py as in import x. If it does not exist, it will look for world.py at the same level as the import. If that is not found, an Exception will be raised.

hello/
    hello.py  # Resolving .world from hello/hello.py
    world/
      __init__.py  # Looks for file here
    world.py  # Looks here second
# If not found, raise an exception

Once resolved, the requested variables inside of the module are returned. If these don't exist an exception will be raised.

# hello/world.py
status = 'Operational'
time = 'Now'

# Inside of hello/hello.py
from .world import status  # 'Operational'

Sticking point

This is something that kept on catching me off-guard.

YOU CANNOT IMPORT A RELATIVE MODULE IN ITS ENTIRETY IN PYTHON 3.

YOU CAN ONLY IMPORT EXPLICIT VARIBLES!

import world  # world.a, world.c are accessible
# No way to do this in Python 3.
# Must be explicit:
from .world import status, time
@jugglinmike
Copy link
Copy Markdown

Thanks, Todd!

@yaaminu
Copy link
Copy Markdown

yaaminu commented Feb 8, 2021

thanks, very useful

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment