from <package> import *
#
Individual .py
files in Python are modules. But a folder containing a bunch of .py
files is a package. This section shows the behaviour of the program when you use the from <package name> import *
syntax.
from importlib import reload
Creating package#
Consider package with two modules. It is created in the following cells.
%%writefile from_package_import_all_files/package/__init__.py
# this is __init__.py - it's not necessary
# but generally better to add it to packages
Overwriting from_package_import_all_files/package/__init__.py
%%writefile from_package_import_all_files/package/square.py
square = """
+----+
| |
| |
| |
+----+
"""
def draw_square():
print(square)
Overwriting from_package_import_all_files/package/square.py
%%writefile from_package_import_all_files/package/triangle.py
triangle = """
*
* *
* *
*******
"""
def draw_triangle():
print(triangle)
Overwriting from_package_import_all_files/package/triangle.py
Entry script#
Here is script that trying to import everything from package created before and shows dir()
output. dir()
returns current namespace - names that can be accessed in a current interpreter run:
%%bash
cd from_package_import_all_files
python3
from package import *
dir_result = dir()
print("Namesapce -", dir_result)
Namesapce - ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
The result is a bit counterintuitive - none of the modules in the package appear in the namespace. To get python to load modules from the package in such a case, you need to specify them in the __all__
dunder of the modules __init__.py
. Read more in the following section.
Load modules (__all__
)#
In __all__
dunder list you can describe modules that need to be imported to namespace when outer script tries to import everything from module.
The following cell modify __init__.py
:
%%writefile from_package_import_all_files/package/__init__.py
__all__=["square"]
from .triangle import draw_triangle
Overwriting from_package_import_all_files/package/__init__.py
Let’s now try to check what we have in such case:
%%bash
cd from_package_import_all_files
python3
from package import *
dir_result = dir()
print("Namesapce -", dir_result)
square.draw_square()
Namesapce - ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'square']
+----+
| |
| |
| |
+----+
The results are worthy of detailed consideration:
We finally have
square
in the namespace and you can use its functions accordingly;But
triangle.draw_triangle
that was defined in conventional way still doesn’t appear in the namespace.
Add object to __all__
#
Note that it’s not possible to add specific obejects from within the module.
The following example attempts to add the triangle.draw_triangle
function to the __all__
dunder.
%%writefile from_package_import_all_files/package/__init__.py
__all__=[
"square",
"triangle.draw_triangle"
]
Overwriting from_package_import_all_files/package/__init__.py
But if you try to run such an option, you’ll get an error:
%%bash
cd from_package_import_all_files
python3
try:
from package import *
except Exception as e:
print(e)
module 'package' has no attribute 'triangle.draw_triangle'