I've simplified my import problems down to this simple base case. Say I have a Python package:
mypkg/
__init__.py
a.py
b.py
a.py contains:
def echo(msg):
return msg
b.py contains:
from mypkg import a # possibility 1, doesn't work
#import a # possibility 2, works
#from mypkg.a import echo # import also fails
print(a.echo())
Running python b.py
produces ImportError: No module named mypkg
on both Python 2.7.6 and Python 3.3.5. I have also tried adding from __future__ import absolute_import
in both cases, same issue.
Expected:
I expect possibility 1 to work just fine.
Why do I want to do this:
Possibility 2 is less desirable. Hypothetically, the standard library could introduce a package called a
(unlikely in this case, but you get the idea). While Python 2 searches the current package first, Python 3+ includes absolute import changes so that the standard library is checked first.
No matter what my reason, possibility 1 is supposed to work, no? I could swear I've done it thousands of times before.
Note: If you write a script external to mypkg
, from mypkg import a
works without issue.
My question is similar to python - absolute import for module in the same directory, but the author implies that what I have should be working.
from mypkg import a
is the correct form. Don't run scripts from inside the Python package directory, it makes the same module available using multiple names that may lead to bugs. Run python -m mypkg.b
from the directory that contains mypkg
instead.
To be able to run from any directory, mypkg
should be in pythonpath.
Try this:
import sys
import os
this_dir = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.dirname(this_dir))
from mypkg import a
print(a.echo())
I think the problem comes from the fact that you don't have a reference to mypkg inside the mypkg folder. Look at what Python is doing when I try to run your example (using the verbose option):
# trying /vagrant/mypkg/mypkg.py
That's why it can find the module, because it doesn't exist. One hack you could do is to have a file called mypkg.py with the line
import a
but that's just your 2nd possibility above in another jacket. Without knowing what you want to accomplish, I would choose the first example on the Intra-package Reference text. I would write b.py as such:
from a import echo
print(echo('message'))
Yes it will not work, because at the moment you call print(mypkg.a.echo())
, mypkg
is still loading (mypkg.__init__
-> mypkg.b
). This is because Python loads parent modules first. https://docs.python.org/3/reference/import.html#searching
What you can do is wrap print(mypkg.a.echo())
into a function:
def echo():
mypkg.a.echo()
And then:
import mypkg.b
mypkg.b.echo()
Or even:
print(sys.modules['mypkg.a'].echo())
Also you can help Python to find your module:
import importlib
mypkg.a = importlib.import_module('mypkg.a')
mypkg.a.echo()