What is a Python package?
Why would I want to create a package using
Creating a package with
__init__.py is all about making it easier to develop large Python projects. It provides an easy way for you to group large folders of many seperate python scripts into a single importable module.
Let's run through some examples
The best way to understand why you would use
__init__.pyand to learn how to use it to create a package is to run through some quick examples!
The code in this tutorial should work for Python 2 or 3. Just remember, if you are using 2 then you will need to use the
from __future__ import print_function functionality.
Say we have three modules we have created:
someFolder |-- stringLength.py |-- stringToUpper.py `-- stringToLower.py
(Remember a module is considered to be any single python file)
Let's say the content of these files is the following:
# stringLength.py def stringLength(inStr): return len(inStr)
# stringToUpper.py def stringToUpper(inStr): return inStr.upper()
# stringToLower.py def stringToLower(inStr): return inStr.lower()
Obviously, these functions are useless, but it helps to serve as a model for the basic concept that we have some python modules that we have already written that are somehow related.
So, without creating a package and using
__init__.py, how do we use the functions in these files?
Well, we can only import these files if they are in the current directory that whatever script we are running is running from.
Well, we can use these files in a new Python script but with one key caveat:
- The files must be in the same directory as the script we are trying to use them in.
To illustrate that, let's create a file called
example1.py that leverages our modules:
# example1.py import stringLength import stringToLower import stringToUpper some_string = "Hello, Universe!" print(stringLength.stringLength(some_string)) print(stringToLower.stringToLower(some_string)) print(stringToUpper.stringToUpper(some_string))
Adding a blank
What if we wanted to seperate these scripts into a folder in order to keep them more organized?
Well, that is where the
__init__.py file comes into play.
First, lets move our scripts into a new subfolder and call it:
string_func. Then create an empty file in that folder called
Here is our new file/folder structure:
someFolder |-- string_func | |-- __init__.py | |-- stringToUpper.py | |-- stringToLower.py | `-- strengthLength.py `-- example1.py
So, now let's test out exactly what
__init__.py allows us to do:
Let's make a new
# example2.py import string_func.stringLength import string_func.stringToLower import string_func.stringToUpper some_string = "Hello, Universe!" print(string_func.stringLength.stringLength(some_string)) print(string_func.stringToLower.stringToLower(some_string)) print(string_func.stringToUpper.stringToUpper(some_string))
So, now we can access our string functions in this manner. This is great, because they are all in a seperate folder, but the syntax is definitely not very succinct. Let's see if we can clean things up a bit by editing our
Adding imports to init.py
__init__.py file and make the following changes:
# __init__.py from .stringLength import stringLength from .stringToLower import stringToLower from .stringToUpper import stringToUpper
Note that the
. before the module name is neccessary as of Python 3 since it is more strict regarding relative imports: https://stackoverflow.com/questions/12172791/changes-in-import-statement-python3?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
And so with that in our
__init__.py we can now shorten our code to:
# example3.py import string_func some_string = "Hello, Universe!" print(string_func.stringLength(some_string)) print(string_func.stringToLower(some_string)) print(string_func.stringToUpper(some_string))
Now the syntax is a lot shorter and you can see that
string_func is behaving like its own module.
So, that is basically what
__init__.py does! It allows you to treat a directory as if it was a python module. Then you can further define imports inside your
__init__.py file to make imports more succinct, or you can just leave the file blank.
There are basically 3 tips I have for debugging import issues:
Use the interactive interpreter (The REPL) to import the modules and see if you are getting what you expect.
Start your script with
python -v -m my_scriptname.pyand then check the output to see exactly where your modules are getting imported from.
Use Pycharm. Pycharm's fantastic introspection abilities mean that you will immeadiately know whether or not your module is being properly imported as it will indicate an error if not. It will sometimes also suggest the proper correction. The community edition is free and if you're a student you can get a free subscription to ALL of their products!
For more information about python modules and packages you can see check the python documentation on it.
As usual, feel free to contact me if you come across any errors in this post!