I'm using PyCharm and Python 3 and I have the next python folder layout:
src/
__init__.py
command/
__init__.py
simpleremote/
__init__.py
Command.py
GarageDoor.py
GarageDoorOpenCommand.py
Light.py
LightOffCommand.py
LightOnCommand.py
RemoteControlTest.py
SimpleRemoteControl.py
I created packages, as you can see. The file with the main method is RemoteControlTest.py which worked perfectly with these imports:
from pythonDesignPatterns.src.command.simpleremote.GarageDoor import GarageDoor
from pythonDesignPatterns.src.command.simpleremote.GarageDoorOpenCommand import GarageDoorOpenCommand
from pythonDesignPatterns.src.command.simpleremote.Light import Light
from pythonDesignPatterns.src.command.simpleremote.command import LightOnCommand
from pythonDesignPatterns.src.command.simpleremote.SimpleRemoteControl import SimpleRemoteControl
Previous to create the init.py files for the packages, I tried to use relative imports instead of the former ones, for example
from .command import LightOnCommand
but it gave me an error (going to call this Case A):
SystemError: Parent module '' not loaded, cannot perform relative import.
so fiddling around I found out that this worked for the same line:
from command.simpleremote.Command import LightOnCommand
and the program was executed succesfully again, but if I use the "Refactor" option from the IDE (PyCharm) and rename "Command" to "command" , writing this line:
from command.simpleremote.command import LightOnCommand
it suddenly shows the error (Case B):
ImportError: No module named 'command.simpleremote'; 'command' is not a package
Which is the problem in each case (A and B)? I can't understand why it would work in between each cases when importing from command.simpleremote. Why not one level further or closer? Why is it working with capital 'C' and not 'c'? Is this case-sensitive?
I've looked at official Python docs, (and webs for PEP302, PEP328 and PEP420) but it's too complex for me in a single night. Can anyone make understand this in a simpler way (or tell me a resource I can read about this explained simpler)?
Thanks in advance
I guess that you run
RemoteControlTest.py
directly.Case A
Python's importer can't go to parent if the module was run directly as script instead of acquiring it going through the package structure.
The Python designers presumably didn't want to let submodules be called directly as scripts so there are no really good solutions for that. Mainly you can
python -m command.simpleremote.RemoteControlTest
whensrc
is either current directory or inPYTHONPATH
orA more detailed discussion of possible solutions can be found at Relative imports in Python 3.
Case B
A consequence of the direct start is that "
src/command/simpleremote
" is in the module search path. "src
" seems also to be added to the path but after "src/command/simpleremote
".Before case B on
from command...
the import mechanism didn't find matching "command
" in "src/command/simpleremote
" and continued looking in "src
" where thecommand
package was found -> success.In case B it finds
command.py
in "src/command/simpleremote
" which isn't a package -> error.