Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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()

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'))

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())
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top