Wamaitha N.
—What is __init__.py
used for in Python?
In Python projects, if you create a file called __init__.py
in a directory then Python will treat that directory as a package. A package in Python is a collection of modules (individual .py files) that can be imported into other Python files.
In older versions of Python (before 3.3), it was necessary to create an __init__.py
file in a package before you could use import statements in the form from mypackage import mymodule
. Since version 3.3 and the implementation of PEP 420, Python will automatically create “Namespace Packages” implicitly in many cases. This means that __init__.py
is now often optional, but it’s still useful to structure your initialization code and define how statements like from mypackage import *
should work.
Let’s take a look at what the __init__.py
file does with an example Python package. Imagine we have a calculator
script that imports a divider
and multiplier
module from an operations
package.
Our directory structure looks like this:
├── calculator.py └── operations ├── divider.py └── multiplier.py
And our three files look like this:
# calculator.py from operations import multiplier, divider mymultiplier = multiplier.Multiplier() result = mymultiplier.multiply(2, 5) print(f"2 x 5 is {result}") mydivider = divider.Divider() result = mydivider.divide(10, 2) print(f"10 / 2 is {result}")
# operations/divider.py class Divider: def divide(self, a, b): return a / b
# operations/multiplier.py class Multiplier: def multiply(self, a, b): return a * b
In Python 3.3 and above, this works fine. When we run from operations import multiplier
, Python treats the operations
subdirectory as a Namespace Package and imports the multiplier
module from that package. In previous versions of Python, this would have raised an error:
File "calculator.py", line 1, in <module> from operations import multiplier ImportError: No module named operations
And simply adding a blank file called __init__.py
in the operations
directory would fix the issue.
touch operations/__init__.py
Now running the calculator.py
script would work as expected:
2 x 5 is 10 10 / 2 is 5.0
__init__.py
do?Even in Python 3.3 and above, creating an __init__.py
file will change the behavior of your scripts, though these changes are more subtle than in older versions of Python. It can automatically define the __file__
metadata of your package, which is useful.
If you import a package and inspect it with Python’s built-in dir
function, you’ll see a difference with and without having an __init__.py
file.
Add the following to the top of calculator.py
:
# calculator.py import operations print(dir(operations)) print(operations.__file__)
This shows us all the variables available in the operations package and prints out its path on the system. Without an __init__.py
file in your operations
subdirectory, you’ll see the following:
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__'] None
You can see that Python has automatically added some metadata in the variables starting and ending with two underscores, like __file__
.
However, the None
on the next line shows that the __file__
variable is blank.
If you create an __init__.py
file in the operations
subdirectory, it is now an explicit package. If you run the calculator.py
file again, you’ll now see some differences in the output:
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__'] /Users/g/python_init_example/operations/__init__.py
Now the full path to the __init__.py
file has been used as the __file__
variable for the operations
package. Python has also added the __builtins__
and __cached__
metadata variables for us.
__init__.py
to run code and control *
importsLarger and more complicated packages often use __init__.py
to better organize code and to run any initialization that should be run automatically when the package is imported.
For example, you could add the line print("Hi from __init__.py")
to your operations/__init__.py
file. Now if you import the operations package, it will run the print
statement immediately:
python_init_example$ python3 Python 3.11.5 (main, Aug 24 2023, 15:09:45) [Clang 14.0.3 (clang-1403.0.22.14.1)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import operations Hi from init
A common thing to define in the __init__.py
is the __all__
variable. This overwrites what modules and functions should be imported when a user runs an import statement in the form from mypackage import *
.
By default, Python does not import modules from a package. So if we changed the first line in our calculator.py
file to import everything from operations
, it would not work.
# calculator.py # broken import unless we explicitly define `__all__` in `__init__.py` from operations import * mymultiplier = multiplier.Multiplier() result = mymultiplier.multiply(2, 5) print(f"2 x 5 is {result}") mydivider = divider.Divider() result = mydivider.divide(10, 2) print(f"10 / 2 is {result}")
If we run calculator.py
now, we’ll get an error:
Traceback (most recent call last): File "/Users/g/python_init_example/calculator.py", line 3, in <module> mymultiplier = multiplier.Multiplier() ^^^^^^^^^^ NameError: name 'multiplier' is not defined
But if we add the following line to operations/__init__.py
:
__all__ = ['divider', 'multiplier']
the calculator.py
script will run as expected:
2 x 5 is 10 10 / 2 is 5.0
Tasty treats for web developers brought to you by Sentry. Get tips and tricks from Wes Bos and Scott Tolinski.
SEE EPISODESConsidered “not bad” by 4 million developers and more than 100,000 organizations worldwide, Sentry provides code-level observability to many of the world’s best-known companies like Disney, Peloton, Cloudflare, Eventbrite, Slack, Supercell, and Rockstar Games. Each month we process billions of exceptions from the most popular products on the internet.
Here’s a quick look at how Sentry handles your personal information (PII).
×We collect PII about people browsing our website, users of the Sentry service, prospective customers, and people who otherwise interact with us.
What if my PII is included in data sent to Sentry by a Sentry customer (e.g., someone using Sentry to monitor their app)? In this case you have to contact the Sentry customer (e.g., the maker of the app). We do not control the data that is sent to us through the Sentry service for the purposes of application monitoring.
Am I included?We may disclose your PII to the following type of recipients:
You may have the following rights related to your PII:
If you have any questions or concerns about your privacy at Sentry, please email us at compliance@sentry.io.
If you are a California resident, see our Supplemental notice.