0

I have two packages, a and b. They are in the same directory, and b is dependent on a (but NOT the other way around). When I run from . import a in b\some_package.py, I get ImportError: cannot import name a. When I run import a (from the appropriate directory), there is no error. Both packages have __init__.pys. This answer explains why fairly well, but does not mention how to fix this. How can I fix this?

File structure:

parent_directory
    a
     __init__.py
     module_in_a.py
    b
     __init__.py
     module_in_b.py (this imports a)
Community
  • 1
  • 1
cat40
  • 318
  • 1
  • 4
  • 13
  • 1
    Are these modules actually part of a package? You haven't mentioned any packages. Why are you trying to perform a relative import? – user2357112 Sep 23 '16 at 22:06
  • @user2357112 I got those two mixed up again. I'll fix that – cat40 Sep 23 '16 at 22:10
  • Okay, why are you trying to import a completely different package with a relative import? Relative imports are for situations like `b.foo` importing `b.bar`, not `b.foo` importing `a`. – user2357112 Sep 23 '16 at 22:15
  • @user2357112 I have two packages in the same directory. A module in one needs access to the other. How do I do that without a relative import, and why not use one? – cat40 Sep 23 '16 at 22:18
  • With a regular import, `import a`, like you already tried. A relative import is simply not the tool for the job. Their role is not whatever you think it is. – user2357112 Sep 23 '16 at 22:20
  • @user2357112 I get `ImportError: no module named a`. I am fairly certain this is because the importing file (in package `b`) cannot see package `a`, because `a` is on the same directory level as `b`, rather than `b\module.py` – cat40 Sep 23 '16 at 22:23
  • What, you get that from just `import a`? You said that worked. If you're getting an ImportError from `import a`, the directory you're trying to import things from isn't on your module search path. You'd need to install your packages (probably in a [virtualenv](http://docs.python-guide.org/en/latest/dev/virtualenvs/)) or manipulate your `sys.path` to have the necessary directory on it, and you might need to [explicitly set `__package__`](https://www.python.org/dev/peps/pep-0366/), depending on how you're running your code. – user2357112 Sep 23 '16 at 22:32
  • @user2357112 Sorry, I forgot to say that `import a` worked in the parent directory, not in `b`. Are relative imports really not usable for cross-module communication? Editing `sys.path` seems like overkill – cat40 Sep 23 '16 at 22:37
  • "Cross-module communication"? Relative imports operate *within* a package. They're not some kind of directory traversal feature. They are an optional alternative syntax for contents of the same package to import each other. – user2357112 Sep 23 '16 at 22:40
  • Relative import are not usable for cross-package communications! Since these two packages are not part of an overall package there is no guarantee in the general sense that these two packages will be installed in the same directory. Things like eggs and site verses dist verses local installs make that a dodgy proposition. If you have multiple packages you need to dip your toe into the package installation world. I use devpi and virtual environments for this type of thing. – tdelaney Sep 23 '16 at 22:45
  • Your post says "ImportError: cannot import name b" when I think it should say "ImportError: cannot import name a". And it would be useful to include `__init__.py` in your directory structure so we can see the situation at a glance. – tdelaney Sep 23 '16 at 22:48
  • If you don't mind a hack, `module_in_b.py` could do `sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))` and then just `import a`. – tdelaney Sep 23 '16 at 22:54
  • @tdelaney doesn't `os.path.dirname(os.path.abspath('.'))` work, and is shorter? – cat40 Sep 23 '16 at 23:02
  • @cat40 That is the current working directory and it will only work if you happen to be sitting in b's parent directory when you import `b`. We don't know where the program that imports b is, but if its on the `PATH` current working directory could be anywhere. – tdelaney Sep 23 '16 at 23:07

1 Answers1

0

Package relative imports cannot refer to modules outside of the package. This is impossible in the general sense because it assumes that module-relative paths are always the same as file system directories. But modules can be installed in many places and can be inside archives such as eggs.

If you install packages a and b, you don't have a problem. Python's virtualenv can help with local installs that don't affect your system python modules. But you can also edit the PYTHONPATH environment variable to point to a place where you have installed a and b or you can change sys.path inside your program. For instance,

b/module_in_b.py

import sys
import os

_my_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
if _my_path not in sys.path:
    sys.path.append(_my_path)
del _my_path

import a
tdelaney
  • 73,364
  • 6
  • 83
  • 116