My Directory structure in /VM/repo/project
is:
__init__.py
scripts/
getSomething.py
__init__.py
classes/
project.py
db.py
__init__.py
from ..classes import project
from ..classes import db
class PROJECT:
def __init__(self):
stuff
class DB:
def __init__(self):
stuff
When I try to run
python getSomething.py
I get the error
Traceback (most recent call last):
File "scripts/getSomething.py", line 4, in < module >
from ..classes import project
ValueError: Attempted relative import in non-package
What am I missing here?
As stated in the error, you're running getSomething
as a main module. But you can't do package relative imports when you aren't in a package. The main module is never in a package. So, if you were to import getSomething
as part of a package...:
# /VM/repo/main.py
from project.scripts import getSomething
Then you would not have the import errors.
Perhaps it is helpful to have a quick discussion on python modules and packages. In general, a file that contains python source code and has the .py
extension is a module. Typically that module's name is the name of the file (sans extension), but if you run it directly, that module's name is '__main__'
. So far, this is all well known and documented. To import a module you just do import module
or import package.module
and so on. This last import statement refers to something else (a "package") which we'll talk about now...
Packages are directories that you can import. Many directories can't be imported (e.g. maybe they have no python source files -- modules -- in them). So to resolve this ambiguity, there is also the requirement that the directory has an __init__.py
file. When you import a directory on your filesystem, python actually imports the __init__.py
module and creates the associated package from the things in __init__.py
(if there are any).
Putting all of this together shows why executing a file inside a directory that has an __init__.py
is not enough for python to consider the module to be part of a package. First, the name of the module is __main__
, not package.filename_sans_extension
. Second, the creation of a package depends not just on the filesystem structure, but on whether the directory (and therefore __init__.py
was actually imported).
You might be asking yourself "Why did they design it this way?" Indeed, I've asked myself that same question on occasion. I think that the reason is because the language designers want certain guarantees to be in place for a package. A package should be a unit of things which are designed to work together for a specific purpose. It shouldn't be a silo of scripts that by virtue of a few haphazard __init__.py
files gain the ability to walk around the filesystem to find the other modules that they need. If something is designed to be run as a main module, then it probably shouldn't be part of the package. Rather it should be a separate module that imports the package and relies on it.