The Python Rabbithole

The Python Rabbithole

Share this post

The Python Rabbithole
The Python Rabbithole
13 Python Import Things I Regret Not Knowing Earlier

13 Python Import Things I Regret Not Knowing Earlier

Liu's avatar
Liu
Oct 05, 2024
∙ Paid
1

Share this post

The Python Rabbithole
The Python Rabbithole
13 Python Import Things I Regret Not Knowing Earlier
Share

1) “import X” VS “from X import Y”

We have 2 files — main.py which we run, and helper.py which we import from.

There are 2 main ways of importing here:

and

Both are valid, and each way has their pros and cons:

In “from helper import testfunc”, we simply need to type testfunc() to use it, whereas in “import helper”, we need to type helper.testfunc()

However, in larger, more complicated applications, “from helper import testfunc” has a higher probability of causing a clash in namespace — ie accidentally overriding another function/variable of the same name.

Conversely, “import helper” will not accidentally override another function/variable with the name testfunc as it is namespaced (helper.testfunc)

2) “from X import Y” VS “from X import *”

from helper import testfunc ONLY imports the testfunc function.

from helper import * imports EVERYTHING in helper.py

While from helper import * might seem more convenient at first, it is actually considered bad practice.

When we use from helper import * , we import everything from helper.py, which also means some of the imported functions/variables might accidentally override existing functions/variables of the same name.

As such, it is often better practice to explicitly state what exactly we are importing rather then importing everything inside a file.

3) __import__ for dynamic imports

^ this allows us to dynamically import modules using strings

4) sys.path and where stuff is imported from

When we import stuff, Python has a list of folders to search from.

We can see this list of folders by printing sys.path

When we import something eg pandas, Python tries to find pandas in the first folder /Users/me/Documents/test

If it exists in this first folder, Python simply imports pandas from here. Otherwise, Python will move on to the next folder /some/other/path and attempt to import pandas from there.

And this repeats til there are no more folders left for Python to search from. And when this happens, we get an ImportError

Quick Pause

I recently wrote a book — 101 Things I Never Knew About Python

Here I’ve compiled 101 cool Python tricks and facts that many (if not most) do not know about. Check it out if you wish to level up your Python knowledge!

Link: https://payhip.com/b/vywcf

5) We can manually add stuff to sys.path

sys.path is a normal list of strings. Python just happens to search for modules from the paths inside sys.path

Let’s say we need to import some function from /some/weird/path/test.py

And we’re working with /our/main/path/main.py — a completely different path elsewhere.

As such, we can simply add /some/weird/path into sys.path so that Python knows that we wish to search from the location /some/weird/path

After adding some/weird/path to sys.path, we can now import from that directory without problem.

6) PEP8 order of imports

I’ve been scolded at work by my techlead for now following this some time ago.

PEP8 (Python Enhancement Proposal 8) is a document stating the best practices for Python code styles.

Link: https://peps.python.org/pep-0008/

Regarding imports, we should ideally order them this way:

  1. Standard library imports eg os, sys, json, re

  2. Related third party imports eg pandas, numpy, fastapi

  3. Local library specific imports eg our_custom_modules

And remember to add a newline character between each group for readability

Note — Python doesn’t enforce this (but your techlead might)

7) __all__ and “exporting” from a file

The special __all__ variable controls what is imported from a file.

We have 2 files — main.py which we run, and helper.py which main.py imports from.

And helper.py contains a bunch of functions, but it has an __all__ variable.

^ here, the __all__ variable makes is such that only hello and hi are exported when we do from helper import *

Here, since only hello & hi are exported from hello.py, main.py only imports hello & hi.

Which means that hola and nihao are NOT imported.

The __all__ variable can thus be used to limit what is exported in a Python module, and is especially useful if our Module is cluttered and contains lots of variables.

8) Variables starting with _ are not imported during “from X import *”

We have 2 files — main.py which we run, and helper.py which main.py imports from.

In helper.py, we have 2 normal functions, and 2 functions with names starting with an underscore _

And when we do ”from helper import *” , variables/functions starting with an underscore _ are NOT imported.

9) The PYTHONPATH env variable

PYTHONPATH is an environment variable that we can choose to define. And if we do define it, PYTHONPATH is automatically added to sys.path

In the following example, we don’t define PYTHONPATH:

In the next example, we set PYTHONPATH to /some/funny/path

As such, /some/funny/path is automatically added to sys.path which we can observe. And now, when we import stuff in Python, Python will automatically search our PYTHONPATH also.

This is useful if we wish to import modules from some other path, but don’t wish to couple our current directory with that location.

10) __name__ during imports

__name__ is another special variable in Python.

When we run a file directly, __name__ defaults to the string value ‘__main__’

Conversely, __name__ in imported files are NOT ‘__main__’ , but the name of the Python file instead.

Here, we run a.py directly. So, __name__ in a.py defaults to ‘__main__’

b.py & c.py are not run directly. Instead, we import from them. As such, __name__ in b.py is simply b, and __name__ in c.py is simply c

This is why we often see if __name__ == “__main__” in Python code — this is to ensure that whatever is inside this block only runs if we are running this specific Python file directly.

Keep reading with a 7-day free trial

Subscribe to The Python Rabbithole to keep reading this post and get 7 days of free access to the full post archives.

Already a paid subscriber? Sign in
© 2025 ZL Liu
Privacy ∙ Terms ∙ Collection notice
Start writingGet the app
Substack is the home for great culture

Share