4

I have a strange (for me) problem with python imports and I would like to understand what is wrong with it.

I have created a demo project with the following directory structure:

├── entry.py
└── foo
    ├── __init__.py
    └── bar
        ├── __init__.py
        ├── sdk.py
        ├── service.py
        └── utils.py

If I run python entry.py, in service.py the following statement works:

from foo.bar import utils

while this does not:

import foo.bar.utils as utils
# entry.py:

from foo.bar.sdk import get_sdk
print(get_sdk())

# foo - __init__.py
# empty on purpose

# bar - __init__.py
from .service import Service

# sdk.py
def get_sdk():
    return "SDK"

# service.py
import foo.bar.utils as utils # wrong import
# from foo.bar import utils # works!
class Service:
    def do_service(self):
        util = utils.get_utility_string()
        print("Doing service call {}".format(util))

# utils.py
def get_utility_string():
    return "This is useful"

By running python entry.py I get:

Traceback (most recent call last):
  File "entry.py", line 1, in <module>
    from foo.bar.sdk import get_sdk
  File "/Users/paloand/Downloads/p_demo/foo/bar/__init__.py", line 1, in <module>
    from .service import Service
  File "/Users/paloand/Downloads/p_demo/foo/bar/service.py", line 1, in <module>
    import foo.bar.utils as utils
AttributeError: module 'foo' has no attribute 'bar'

From my understanding in entry.py when the get_sdk symbol is getting imoprted from sdk module, foo package is being imported as well. While importing foo in bar the __init__.py file requests the import of the Service symbol. So while foo is being imported it is required again in service.py.

Link to the uploaded demo project in my Dropbox: Demo

I have read this question and all the answer but there I could not extract any information there. I also found this bug but I am not sure if it applies here. I read also the common traps of import in python but could not find this one.

I want to understand the difference and what is really happening.

I am using python 3.6

Thank you

EDIT

Updated with error message

EDIT 2

I have tried python -vv entry.py in both cases. The relevant logs are in the paste: https://pastebin.com/J9guMqJS.

In both cases the import order is the same, in the "bad" case this import fails:

import 'foo.bar.utils' # <_frozen_importlib_external.SourceFileLoader object at 0x1103ddf28>
Sanandrea
  • 2,112
  • 1
  • 27
  • 45

0 Answers0