0

I have the following project:

apack/
  apack/
    __init__.py
    apack.py
    aux.py
  setup.py

apack.py:

def foo(x):
    return x

aux.py:

from apack import foo

def bar():
    return foo() + 1

setup.py:

from setuptools import setup, find_packages

setup(
    name='apack',
    packages=find_packages()
)

I install the package with pip install .. However, the result is a an empty package:

>>> import apack
>>> apack.foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'apack' has no attribute 'foo'

What I would like to have is:

>>> import apack
>>> apack.foo()
>>> apack.bar()

There is a number of similar questions here (e.g., 1, 2). However, none of them is minimal enough for me to understand why my example does not work.

foki
  • 8,624
  • 6
  • 33
  • 32

1 Answers1

2

When you import the package it invokes the __init__ file of the package. You can confirm this in your python interpreter.

>>> import json
>>> json.__file__
'<PATH>\\lib\\json\\__init__.py'

So to have foo and bar available from your package level you have to import foo and bar into the __init__ file of your package. ie,

from .apack import foo
from .aux import bar
Abdul Niyas P M
  • 18,035
  • 2
  • 25
  • 46
  • To add: and subsequently, in `aux.py` instead of `from apack import foo`, import relatively: `from .apack import foo`. – felipe Nov 27 '21 at 04:08
  • @Felipe Why? What I currently have seems to work. – foki Nov 27 '21 at 17:25
  • @Felipe There is this excerpt from PEP https://stackoverflow.com/a/12738912/1398282. However, the explanation involves a series of vaguenesses such as "a module inside a package can't easily import itself ". Why would a module ever import itself? A module always has access to its own namespace, what do I get by importing a module to itself? – foki Nov 27 '21 at 17:36
  • 1
    Regarding the relative import - honestly, before your question (and my subsequent research thereafter) I always thought it was recommended. It seems [PEP8](https://www.python.org/dev/peps/pep-0008/) actually recommends the opposite -- absolute over relative imports. Regarding the last comment, I believe they mean that relative import allows you to import the module in-itself. In other-words, inside `aux.py` you can do `from . import aux`. The only reason why I could see one wanting to do this is to specify the module for every func/objs/declarable inside the module's namespace. – felipe Nov 27 '21 at 22:13
  • 1
    Imagine `aux.py` importing `foo.bar()` and having a `bar()` function inside of it. Doing `from . import aux` inside `aux.py` will allow you to use the `bar()` function as `foo.bar()` and `aux.bar()`, differentiating both. Again - my only thoughts as to _why_ this would be useful. I've never encountered this in the wild myself. – felipe Nov 27 '21 at 22:14