87

Suppose I have a module foo.py and a package foo/. If I call

import foo

which one will be loaded? How can I specify I want to load the module, or the package?

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
Charles Brunet
  • 21,797
  • 24
  • 83
  • 124

3 Answers3

33

I believe the package will always get loaded. You can't work around this, as far as I know. So change either the package or the module name. Docs: http://docs.python.org/tutorial/modules.html#the-module-search-path

Zach Kelling
  • 52,505
  • 13
  • 109
  • 108
  • 5
    Hi, can you please provide a reference for your claim? I don't see anything in the documentation link provided that says the package will always be loaded in preference to the module. – wim Apr 21 '16 at 01:59
  • 4
    This answer is incorrect. The linked docs (for both Python 2 and 3) state that the directory of the current script is given preference in the search order. See also: http://python-notes.curiousefficiency.org/en/latest/python_concepts/import_traps.html#the-name-shadowing-trap – Isaiah Norton Apr 10 '19 at 20:18
  • 1
    While docs says package is preferred over module in my experience it's not true, at least in python 2.7. It seems like in Python 2.7 import seeks for the module at parent (but not child) directories until it finds it, so **installed packages** will be checked at the end of resolving. – Qback Apr 08 '20 at 11:03
20

Actually, it is possible, by manually guiding the import machinery to use a .py file instead of directory. (This code is not well tested, but seems to work). UPDATE 2020: Note that this requires using custom import_module() function instead of normal import statement. However, with modern Python3 and its importlib, it might be possible to make the bare import statement to work the same way too. (Note that this answer shows flexibility which Python offers. It's not an encouragement to use this in your applications. Use this only if you know what you're doing.)

File foo.py

print "foo module loaded"

File foo/__init__.py

print "foo package loaded"

File test1.py

import foo

File test2.py

import os, imp

def import_module(dir, name):
    """ load a module (not a package) with a given name 
        from the specified directory 
    """
    for description in imp.get_suffixes():
        (suffix, mode, type) = description
        if not suffix.startswith('.py'): continue
        abs_path = os.path.join(dir, name + suffix)
        if not os.path.exists(abs_path): continue
        fh = open(abs_path)
        return imp.load_module(name, fh, abs_path, (description))

import_module('.', 'foo')

Running

$ python test1.py 
foo package loaded

$ python test2.py 
foo module loaded
pfalcon
  • 6,724
  • 4
  • 35
  • 43
abb
  • 684
  • 6
  • 15
  • 1
    So, it's possible by manually hacking how imports are processed. That's great, and a worthy answer. But note that by manual hacking, almost anything is possible. So, I'm inclined to edit this answer, to emphasize "manual hacking" aspect. – pfalcon Dec 26 '20 at 09:11
  • Also note that hacking at the proper level (`importlib` import hooks), it might be possible to make the bare `import foo` to have a preference for `foo.py` the module instead of `foo/` the package. – pfalcon Dec 26 '20 at 09:12
15

Maybe you want to move your classes from foo.py module to __init__.py.

This way you'll be able to import them from the package as well as importing optional subpackages:

File foo/__init__.py:

class Bar(object):
...

File foo/subfoo.py:

class SubBar(object):
...

File mymodule.py:

from foo import Bar
from foo.subfoo import SubBar
Grzegorz Skibinski
  • 12,624
  • 2
  • 11
  • 34
steppo
  • 583
  • 3
  • 20