Files, folders, __init__.py, and imports
Apologies if this question turns out to not be Pythonista-specific, but I'm having a hard time understanding why my folders + imports break when I move things in Pythonista.
When I place foo.py somewhere in Pythonista (at the top level, or within a folder, or within a folder that contains an empty init.py, or a deeper folder) what are the rules for doing an import both (a) from foo.py, and (b) of foo.py.
Is site_packages special? Any others?
Do these rules depend on where the top-level main file being run is located?
import foostatement (which internally becomes
foo = __import__("foo")) looks through all directories listed in
sys.pathfor a module with the name
sys.pathincludes a number of internal Pythonista folders holding the standard library and extensions that come with the app, as well as the main Script Library aka. Documents folder and site-packages. Any other folder will not be searched when importing. This means that having
foo.pyin either Documents or site-packages makes it importable, but having it in subfolders doesn't.
Packages are a special type of module source. Any folder containing an
__init__.pyfile is considered a package and can be imported. A package may contain any number of sub-modules and sub-packages. Say you have a folder
fooin Documents or site-packages containing the files
spam.py. The statement
import foowill import the
__init__.pyfile as the name
import foo.barwill first import
__init__.pyto the name
foo, then import
bar.pyas the attribute
foo.bar. (i. e. importing a submodule will also import all parent modules from top to bottom.) Do note however that importing a module will normally not import any of its submodules. Some packages (such as
sympy) do this in their
__init__.pys for convenience, so for example writing
import numpywill automatically give you a useful set of NumPy's modules without needing to explicitly import them.
There is also a feature for imports inside packages called relative imports. For instance, in
bar.pyfrom our above example, we could write
from . import spamto import
spam.pyfrom the current package. Unlike
from foo import spamthis import will work no matter what you name the
foopackage. Relative imports only work in scripts that are not the main script though. If
from . import spamand we do
import foo.barfrom another script, the code will run fine - but if we run
bar.pyas the main script it will error because the main script is never considered part of a package. This may seem an unnecessary restriction, but is important in modules that depend on their parent packages'
__init__.pys being run beforehand.
(This is a very lengthy explanation and probably more than you asked for, but hopefully it'll answer any import questions you may have ;)
This is a great resource. Thanks for all the detail. It demystifies much of what goes on in import.
Very helpful, thanks so much!