Question

suppose I have a folder structure that looks like this:

.
├── A
│   ├── a.py
│   └── b.py
└── main.py

The files have the following content:

b.py:

class BClass:
    pass

a.py:

from b import BClass

main.py:

from A import a

If I run python3.3 A/a.py or python3.3 B/b.by, there are no errors. However, if I run python3.3 main.py, the following error occurs:

Traceback (most recent call last):
  File "main.py", line 1, in <module>
    from A import a
  File "/tmp/python_imports/A/a.py", line 1, in <module>
    from b import BClass
ImportError: No module named 'b'

Changing the import-line in a.py to import A.b works, but obviously python3.3 A/a.py will fail then. I am not actually interested in running python3.3 A/a.py but I want the module to be importable from multiple locations. Therefore a.py should import b.py regardless of where a.py is imported.

How can this issue be resolved?

Was it helpful?

Solution

Besides the __init__.py I mentioned in my comment which is mandatory for packages, you need to import the sibling module relatively:

from .b import BClass

Then it also works in Python 3.

Alternatively you can of course import the full name:

from A.b import BClass

But then your module isn't relocatable as easily within your package tree.

In neither way, though, you are able to use a.py as a standalone. To achieve this you would need to surround the import statement with try/except and try a different version in case the first one fails:

try:
  from .b import BClass
except ValueError:
  from b import BClass

But that is understandable. In a larger system, modules might depend on other modules somewhere in the package, otherwise they maybe should not be part of a package but standalone. And if there are such dependencies, using a module as if it was a standalone will of course be a problem.

OTHER TIPS

You need an __init__.py file (empty will be just fine) in the A directory. Otherwise, python won't recognize it as a package.

Now you're A is a package, you should use either absolute imports or explicit relative imports. In this case, in A/a.py either use from A.b import BClass or from .b import BClass.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top