In the current working directory:
The package foo
contains the module bar.py
, along with an empty __init__.py
file.
For argument's sake, the module bar.py
contains the following code:
def print_message():
print 'The function print_message() prints this message'
print 'The module \"bar\" prints \"bar\"'
Expected behaviour upon import foo
:
foo.bar
to print The module "bar" prints "bar"
foo.bar.print_message()
to print The function print_message() prints this message
Instead, I struggle with the import of the bar.py
module:
On one hand, using from foo import bar
then allows to call
bar.print_message()
On the other hand, if I import foo
, then foo.bar
yields the
error in the title: AttributeError: 'module' object has no attribute 'bar'
(and so does foo.bar.print_message()
)
All the best rated questions on SO I've skimmed through so far, with regards to AttributeError
, feature an answer related to something within the module, not the import itself. Also, Kernel is restarted between each attempt.
Question: Not a blocking point as such but it bugs me down not to understand that behaviour. I'm rather inexperienced, so what fondamental concept am I missing here? Thank you,
When you import foo, you just imported the package, not any of the modules, so when you called bar, it looked in the init.py file for bar, and that file doesn't have bar in it. If you don't import bar into the modules global namespace, it has no idea what bar is, which is why you got an error.
import foo
print(dir(foo)) # ['__builtins__', ...,'__spec__', 'print_message']
from foo import bar
print(dir(foo)) # ['__builtins__',..., 'bar', 'print_message']
You could add from . import bar
to the init.py file. This would make foo aware of bar when it runs the init.py file on import.
https://docs.python.org/3/tutorial/modules.html has some information about modules and packages, and there's some really good info in this post here Importing packages in Python