0

I have a package of the following form:

$ ls folder
entry_point.py  hello.py  __init__.py  utils.py

This is a package, and I can treat it as such:

$ python2.7
>>> import folder.utils
>>>

I want to use relative imports between these Python modules.

$ cat folder/entry_point.py 
from hello import say_hello

if __name__ == "__main__":
    say_hello()
$ cat folder/hello.py 
from .utils import say

def say_hello():
    say()
$ cat folder/utils.py
def say():
    print "hello world"

I know I can't use relative imports at the entry point, where I call the interpreter. However, I still get ImportError from my imported files:

$ python2.7 folder/entry_point.py 
Traceback (most recent call last):
  File "folder/entry_point.py", line 1, in <module>
    from hello import say_hello
  File "/tmp/folder/hello.py", line 1, in <module>
    from .utils import say
ValueError: Attempted relative import in non-package

This is rather counterintuitive, it is a package, it's just not treated as one due to entry_point.py having __name__ set to __main__ (in line with PEP 328).

I'm surprised that hello.py has a __name__ of hello rather than folder.hello. This stops me using relative imports in hello.py.

How do I use relative imports in this package? Am I forced to move hello.py and utils.py to a libs subpackage?

Wilfred Hughes
  • 29,846
  • 15
  • 139
  • 192

1 Answers1

0

If you want folder to be a module inside a bigger project and you want to be able to run entry_point.py for using your folder module - move entry_point.py one level up:

from folder.hello import say_hello

if __name__ == "__main__":
    say_hello()

Import paths - the right way?

Community
  • 1
  • 1
warvariuc
  • 57,116
  • 41
  • 173
  • 227
  • Excellent, thanks. It turns out `__name__` is mutable so it would be possible to do `__name__ = 'folder.hello'`. Your solution is the most elegant available though. – Wilfred Hughes Feb 27 '12 at 15:24