Search code examples
pythonmodulepackageattributeerror

AttributeError: 'module' object has no attribute 'xxxx'


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:

  1. foo.bar to print The module "bar" prints "bar"
  2. 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,


Solution

  • 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