Package Initialization
In this lesson, you’ll learn about package initialization. If a file named __init__.py
is present in a package directory, it is invoked when the package or a module in the package is imported. You can use this to execute package initialization code, for example for the initialization of package-level data.
Consider the following __init__.py
file:
print(f'Invoking __init__.py for {__name__}')
alist = ['spam', 'bacon', 'eggs']
Add this file to the pkg
directory from the above example:
Now, when the package is imported, the global list alist
is initialized:
>>> import pkg
Invoking __init__.py for pkg
>>> pkg.alist
['spam', 'bacon', 'eggs']
>>> pkg.mod1
Traceback (most recent call last):
File "<input>", line 1, in <module>
pkg.mod1
AttributeError: module 'pkg' has no attribute 'mod1'
A module in the package can access the global by importing it in turn:
def load_data():
print('loading data using mod1.load_data()')
from pkg import alist
print(f'This is from pkg - {alist}')
class Customer:
pass
Here’s what you get:
>>> from pkg import mod1
Invoking __init__.py for pkg
>>> mod1.load_data()
loading data using mod1.load_data()
This is from pkg - ['spam', 'bacon', 'eggs']
Revert mod1.py
to the previous version by changing load_data()
to no longer use the import
from pkg
:
def load_data():
print('loading data using mod1.load_data()')
class Customer:
pass
You can also use __init__.py
to effect automatic importing of modules from a package. For example, earlier you saw that the statement import pkg
only places the name pkg
in the caller’s local symbol table and doesn’t import any modules. Let’s say that __init__.py
in the pkg
directory contains the following:
print(f'Invoking __init__.py for {__name__}')
import pkg.mod1, pkg.mod2
Then, when you execute import pkg
, modules mod1
and mod2
would be imported automatically:
>>> import pkg
Invoking __init__.py for pkg
>>> pkg.mod1.load_data()
loading data using mod1.load_data()
>>> x = pkg.mod2.Location()
>>> x
<pkg.mod2.Location object at 0x10e1c2dd8>
Note: Much of the Python documentation states that an __init__.py
file must be present in the package directory when creating a package. This was once true. It used to be that the very presence of __init__.py
signified to Python that a package was being defined. The file could contain initialization code or even be empty, but it had to be present.
Starting with Python 3.3, Implicit Namespace Packages were introduced. These allow for the creation of a package without any __init__.py
file. Of course, it can still be present if package initialization is needed. But it is no longer required.
00:00
In this video, you’re going to learn about package initialization. When talking about package initialization, you need to learn about the __init__.py
file.
00:11
If a file named __init__.py
is present in a package directory, it’s going to be invoked when the package or a module inside that package is imported. The placement for the __init__
file will look like this.
00:23
So, here’s the directory pkg/
(package), and inside of it will be __init__.py
, and then the two modules. Let me show you how this works with some code.
00:35
So over here in the EXPLORER, you can see the directory for pkg/
, and if I open it up, there’s still mod1.py
and mod2.py
.
00:43
So what you need to do is create a new file __init__.py
inside there. __init__.py
. This file can be used to execute package initialization code.
00:58
This might be something that’s specific for package-level data. In this case, let’s make __init__.py
have a print()
statement to show that it’s been executed,
01:10
and then show its name, again using the __name__
variable that you learned about earlier. And then one other thing you can have in here is a global variable.
01:21
Let’s say there’s a list, and just call it alist
,
01:29
and it’s got three strings inside of it. So, here’s __init__.py
. __init__.py
when imported would run this code, printing out that it’s f'Invoking __init__.py for {__name__}'
, and then it also assigns this global variable. Okay. So again, here are all the items inside your package.
01:47
From the terminal, start your REPL. What happens when you import pkg
now? Well, you’ll actually see something a little different. It will then print this out, and show that it’s imported pkg
.
02:01
But also, under pkg
you can see that alist
is there. Importing pkg
imports that __init__
file automatically, executing the code and importing the objects that were part of it.
02:16
Now, the other modules are not here, but here’s something kind of interesting. Go back to mod1.py
.
02:27
A module inside the package can access that global list by importing it in turn. This could be imported inside of mod1
. To do that, again, you might remember load_data()
prints this statement out, but it could also print…
02:54 Printing out that list. Make sure that you save, and then exit and re-enter the REPL.
03:05
What happens if you take from pkg
and import simply mod1
? A couple of things. One, it’s going to run the code from __init__.py
, Invoking __init__.py for pkg
.
03:17
And I want to re-stress this, that importing one of the modules also executes the code in __init__.py
. Now, mod1
has the load_data()
function inside of it, and if you call it, here you can see the two things. It’s printing the first statement, which was loading data using mod1.load_data()
, but then it’s also printing the second statement after it’s imported the alist
global variable.
03:46
Another use for the __init__.py
file is that it can be used to automatically import the modules from a package. Let me show you what that looks like.
03:57
Back inside __init__.py
, get rid of the global alist
variable. And instead, after it shows that it’s been invoking it with that print()
statement, import pkg.mod1, pkg.mod2
.
04:11
So here, when executing the code inside of __init__.py
, it’s going to import the two modules. So, go ahead and save.
04:24
What happens if you import pkg
? It looks like it’s doing the same thing. It is Invoking __init__.py for pkg
—it’s printing that out.
04:32
But also, you can see here pkg
has these modules available now. It’s imported them, so pkg.mod1
has the Customer
class and load_data()
.
04:44
Now, this might give me an error because I didn’t change mod1
back. It can’t find the alist
from pkg
, so I need to change that.
04:54
Back inside mod1
, go ahead and delete this line,
05:06
Now exit and restart the REPL one more time. So here we go. import pkg
, and then you can see pkg.mod1.load_data()
. Again, no issues because it’s just printing that out.
05:18
You could make an object using pkg.mod2
. Create a Location
. So, x
is using that. You can see that import pkg
with that __init__
code of it importing pkg.mod1
and pkg.mod2
, it’s importing both modules automatically.
05:38
In the next video, I’ll show you about importing using the wildcard asterisk (*
) from a package.
Chris Bailey RP Team on May 13, 2020
Hi @jeffwashcloth, I’m using VSCode. Here is a course on setting it up.
jeffwashcloth on May 13, 2020
Great, thanks for the info
srisaisousar on July 8, 2020
init.py file is not executed in python 3.8.2 Why ?
Andy Pickett on Feb. 23, 2021
Great tutorial Chris. I found RealPython through the podcasts which, again are fantastic so thanks!
I’m sitting here laughing at myself as Dunder has been one of my revision topics for the last few days. I couldn’t seem to retain what they were and how they are used. (Still some work to go) …but when my brain suddenly realised that Dunder must mean DoubleUNDERscore it all became clear. Strangely nothing I’ve read so far had mentioned that and yet it seems like such a good way of anchoring them.
Hope this is useful to anyone else trying to learn them too!
Become a Member to join the conversation.
jeffwashcloth on May 13, 2020
What is the environment used in these videos? It’s pretty nifty, with its own file explorer, interpreter, and editor.