How do I make these relative imports work in Pytho

2019-02-19 08:38发布

问题:

I have a directory structure that looks like this:

project/
        __init__.py
        foo/
            __init.py__
            first.py
            second.py
            third.py
        plum.py

In project/foo/__init__.py I import classes from first.py, second.py and third.py and put them in __all__.

There's a class in first.py named WonderfulThing which I'd like to use in second.py, and want to import by importing * from foo. (It's outside of the scope of this question why I'd like to do so, assume I have a good reason.)

In second.py I've tried from .foo import *, from foo import * and from . import * and in none of these cases is WonderfulThing imported. I also tried from ..foo import *, which raises an error "Attempted relative import beyond toplevel package".

I've read the docs and the PEP, and I can't work out how to make this work. Any assistance would be appreciated.

Clarification/Edit: It seems like I may have been misunderstanding the way __all__ works in packages. I was using it the same as in modules,

from .first import WonderfulThing
__all__ = [ "WonderfulThing" ]

but looking at the docs again it seems to suggest that __all__ may only be used in packages to specify the names of modules to be imported by default; there doesn't seem to be any way to include anything that's not a module.

Is this correct?

Edit: A non-wildcard import failed (cannot import name WonderfulThing). Trying from . import foo failed, but import foo works. Unfortunately, dir(foo) shows nothing.

回答1:

Edit: I did misunderstand the question: No __all__ is not restricted to just modules.

One question is why you want to do a relative import. There is nothing wrong with doing from project.foo import *, here. Secondly, the __all__ restriction on foo won't prevent you from doing from project.foo.first import WonderfulThing, or just from .first import WonderfulThing, which still will be the best way.

And if you really want to import a a lot of things, it's probably best to do from project import foo, and then use the things with foo.WonderfulThing instead for doing an import * and then using WonderfulThing directly.

However to answer your direct question, to import from the __init__ file in second.py you do this:

from . import WonderfulThing

or

from . import *