There comes a point in a beginner Python developer's life when he wants to leave the nest and start importing and reusing his own functions.
However, just like with any programming language, there are conventions and syntax that dictate how to export or import code to different modules. In this article, we are going to work through a simple example and discover some of the common ways to import your own code from other files.
Importing Your Own Function
Let's create a file called app.py
. Inside of the file add the following code.
# app.py
from example import example
print(example.yell("My name is Jarrett"))
# Output
# My name is Jarrett!
This file is importing a file named example
from a module with the same name. The assumed project directory for this application is,
.
├── app.py
└── example/
│
└── example.py
Next, create a folder named example
with the file example.py
inside. If you look back at app.py
you see that the file expects the function yell()
to exist inside of example
. Add the following code to example.py
.
# example.py
def yell(phrase):
return phrase + "!"
After saving the file, we can go back to app.py
and run the script. Now that yell
exists you should see My name is Jarrett!
printed to console. Or, whatever string you fed into the function. Nothing to it!
Not quite.
Correctly, Importing Your Own Functions.
To begin, let's lay out what the import
keyword does.
The import
statement combines two operations; it searches for the named module, then it binds the results of that search to a name in the local scope. (Docs)
Although the above code works it could create problems down the line. Let's take a look at the documentation.
When importing the package, Python searches through the directories on sys.path
looking for the package subdirectory.
The__init__.py
files are required to make Python treat directories containing the file as packages. This prevents directories with a common name, such asstring
, unintentionally hiding valid modules that occur later on the module search path. In the simplest case,__init__.py
can just be an empty file, but it can also execute initialization code for the package or set the__all__
variable, described later.
To save ourselves from hard-to-diagnose bugs down the road, we need to add an __init__.py
file alongside our example.py
file.
.
├── app.py
└── example
├── __init__.py
└── example.py
We don't need to make an adjustment to app.py
. We can run the function with the same import statement. However, just to show a different type of import style, let's change the code to what's below.
from example.example import yell
print(yell("My name is Jarrett"))
# Output
# My name is Jarrett!
This can reduce code down in our file, and also allows us to import multiple functions from example.example
.
Creating Python applications are different between common conventions and Python frameworks. Creating Flask or Django applications have different recommended project structures.
These project structures are to avoid bugs with circular importing or for better organization.
Another Set-Up
Our first application put the "runner" file outside of the module. Another common convention is to create the runner file inside the module.
.
└── example
├── __init__.py
├── example.py
└── core.py
Our core.py
file is inside the module. This reduces our import statement by one step.
# core.py
from example import yell
print(yell("My name is Jarrett"))
Or, we could do a straight import [module]
statement that is common to built-in modules in Python.
import example
print(example.yell("My name is Jarrett"))