1

I asked a similar question yesterday, but have acquired a really odd problem since then. With this directory structure:

app/
    models/
        __init__.py
        user.py
        other.py
    pages/
        __init__.py
        pages.py

The models/__init__.py file has this line:

__all__ = ['user', 'other']

and the pages/__init__.py has

__all__ = ['pages']

In pages.py, in order to use any of the classes in user.py or other.py, I have to have

from models import *
import models

at the top, and then I can declare a User class like this:

my_user = models.user.User()

If I exclude either of the import-ing statements at the top, I get errors like

"Class user has no attribute User"

Any help would be appreciated. I love Python, but I wish it's import functionality worked more like PHP's.

2
  • 3
    It's the first time I've heard someone saying they'd like Python to work like PHP... Commented Feb 18, 2010 at 17:26
  • ha, yea it's the first time i've said it too... Commented Feb 18, 2010 at 18:15

3 Answers 3

1

There are two options, depending on where you want to be explicit and how much you want available "by default" (which also means forced).

In those __init__ files you could use:

# models/__init__.py shown:
import user, other                 # ambiguous relative import
from . import user, other          # relative import
from app.models import user, other # absolute import

Or, where you would otherwise just have import models, use:

from models import user, other
# or:
import models.user, models.other

The latter form is more widely preferred.

Sign up to request clarification or add additional context in comments.

1 Comment

i put from app.models import user, other and it works great, thanks
1
import models.user

Comments

1

One thing that can be real helpful when you're learning python (or debugging), is to run interactively and use the dir() function to see what lives where:

>>> dir()
['__builtins__', '__doc__', '__name__', '__package__']
>>> import models
>>> dir(models)
['__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__']
>>> models.user
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'user'
>>> from models import *
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'models', 'other', 'user']
>>> dir(models)
['__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__','__path__', 'other', 'user']
>>> user
<module 'models.user' from 'C:\test\models\user.py'>
>>> models.user
<module 'models.user' from 'C:\test\models\user.py'>
>>> user.User
<class 'models.user.User'>

Update: fixed output.

5 Comments

What is the content of your models/__init__.py? As the question is stated, import models; models.user will give an AttributeError. (Does your sample have import user in models/__init__.py? That would explain your different results.)
@Roger - my models/__init__.py is just __all__ = ['user', 'other'].
Then I'd expect you to get what I get: codepad.org/yWnKyVAW. Did you have an earlier import models.user or similar? (That import will modify the models module object.)
when i just use import models or from models import * and run dir(models) i get "['all', 'builtins', 'doc', 'file', 'name', 'package', 'path']". I have to have both of those statements in order for users and other to be included.
@Roger I see what the problem is now. I had leftovers in the local scope from doing a from models import *. Fixed it up.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.