1

I just noticed that relative import like this:

from .foo import myfunc
print myfunc  # ok
print foo  # ok

imports both foo and myfunc. Is such behaviour documented anywhere? Can I disable it?

-- Update

Basically problem is following.

bar/foo/__init__.py:

__all__ = ['myfunc']

def myfunc(): pass

bar/__init__.py:

from .foo import *
# here I expect that there is only myfunc defined

main.py:

import foo
from bar import *  # this import shadows original foo

I can add __all__ to the bar/__init__.py as well, but that way I have to repeat names in several places.

Vladimir Mihailenco
  • 3,382
  • 2
  • 24
  • 38
  • Please provide information about your package layout and the file these statements occur in. (My guess is that these lines are in `__init__.py`.) – Sven Marnach Jul 20 '12 at 14:51
  • @SvenMarnach, yes, __init__.py . I will update question. – Vladimir Mihailenco Jul 20 '12 at 14:53
  • it is another reason to avoid wildcard imports. – jfs Jul 20 '12 at 15:13
  • Your actual problem seems to be that `from bar import *` shadows a name. This is one of [many reasons why you shouldn't use `from bar import *` in scripts](http://stackoverflow.com/questions/2386714/in-python-why-is-import-bad). – Sven Marnach Jul 20 '12 at 15:14
  • btw, absolute import behaves the same: `from bar.foo import myfunc` – jfs Jul 20 '12 at 15:16

1 Answers1

2

I am assuming your package layout is

my_package/
    __init__.py
        from .foo import myfunc
    foo.py
        def myfunc(): pass

The statement from .foo import myfunc first imports the module foo, generally without introducing any names into the local scope. After this first step, myfunc is imported into the local namespace.

In this particular case, however, the first step also imports the module into the local namespace: sub-modules of packages are put in the package's namespace upon importing, regardless from where they are imported. Since __init__.py is also executed in the package's namespace, this happens to conincide with the local namespace.

You cannot reasonably disable this behaviour. If you don't want the name foo in your package's namespace, my advice is to rename the module to _foo to mark it as internal.

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • Thanks. By some reason I thought that this behaviour is unique to relative imports, but actually absolute imports behave the same way. I am lucky that I did not hit this behaviour before :) – Vladimir Mihailenco Jul 20 '12 at 15:16
  • @VladimirMihailenco: Note that "this behaviour" is also the only sensible thing to do for Python. The `import` statement imports `my_package.foo`, so after the import, `my_package.foo` should better be available. – Sven Marnach Jul 20 '12 at 15:21
  • yes, I have no excuses :) Looks like I misused `__all__` and wildcard imports all the time. – Vladimir Mihailenco Jul 20 '12 at 15:39