Trivial python import fails

Question

I'm confused on why a simple absolute import is failing. Following the Python packages tutorial, I have package with a single subpackage:

sound/
    __init__.py
    top.py
    formats/
        __init__.py
        a.py
        b.py

a.py contains:

def foo():
    print("foo")

b.py contains:

from a import foo

def bar():
    foo()

if __name__ == "__main__":
    bar()

top.py contains:

from formats import b    

if __name__ == "__main__":
    b.bar()

Both __init__.py files are empty. From sound/formats/, running b prints foo as expected. But from sound/, running top produces the error:

File ".../sound/top.py", line 1, in <module>
  from formats import b
File "...\sound\format\b.py", line 1, in <module>
  from a import foo
ImportError: No module named 'a'

(Note the strange appearance of forward slashes in the first line and back slashes in the second. Python 3.5, Windows 7 Pro.) This shouldn't be that complicated -- what syntax is necessary to allow b to consistently import a?

----- EDIT -----

Running unittest is the question I should have found before asking this one. It also contains a great pointer to the Python Project Howto.


Show source
| python   2017-01-03 22:01 1 Answers

Answers ( 1 )

  1. 2017-01-03 23:01

    That's really not how you should be running your code.

    With Python packages you shouldn't be in the folder that contains the files when you're running the code. That'd be like going to C:\Python35\Lib\site-packages\http\* and then running py -3 server.py. Ew. Don't do that.

    Instead, use Python the way it expects to be used!

    ⚘ python --help | grep -e -m                                     
    usage: python [option] ... [-c cmd | -m mod | file | -] [arg] ...
    -m mod : run library module as a script (terminates option list)
    

    You're creating modules, but you want to be able to run them as a script. Turns out that you can do that!

    > cd ../..
    > dir
    sound
    > python -m sound.formats.b
    foo
    > python -m sound.top
    foo
    

    *I think that's the path but it's been a while since Windows for me. If it's wrong, I'm just trying to make a point here!

◀ Go back