27

Lets say I have the following python source file layout:

lib/foo.py
lib/foo/bar.py

and then in my source code:

from foo import gaz

I get an import error:

ImportError: No module named foo

How can I have a .py file and a directory with the same name so I can do the following:

 from foo import gaz
 from foo.bar import wakawaka
feetwet
  • 3,248
  • 7
  • 46
  • 84
David Williams
  • 8,388
  • 23
  • 83
  • 171
  • http://stackoverflow.com/questions/279237/python-import-a-module-from-a-folder – Moj Apr 26 '13 at 21:08
  • 2
    @Moj not the same. That post is about relative imports. The issue im trying to figure out is how to have a .py file with the same name as a directory *in the same directory* and then import from the .py – David Williams Apr 26 '13 at 21:08

2 Answers2

19

The actual problem you are having, using a single import, is due to the packages having the precedence over modules:

Note that when using from package import item, the item can be either a submodule (or subpackage) of the package, or some other name defined in the package, like a function, class or variable. The import statement first tests whether the item is defined in the package; if not, it assumes it is a module and attempts to load it. If it fails to find it, an ImportError exception is raised.

Anyway I'd strongly suggest to rename the file or the directory since you cannot import more than one module with a given name. The problem occurs because each module/package object is stored into sys.modules, which is a simple dict and thus it cannot contain multiple equal keys.

In particular, assuming foo.py and the foo directory are in different directories(and if they aren't you still can't import foo.py), when doing:

from foo import gaz

It will load foo.py and put the module into sys.modules, then trying to do:

from foo.bar import wakaka

Will fail because the import tries to use the module foo.py instead of the package.

The opposite happens if you first import foo.bar; the imports will use the package instead of the module.

Bakuriu
  • 98,325
  • 22
  • 197
  • 231
  • The only import statement I am trying to execute is `from foo import gaz` where the class `gaz` is defined in foo.py. Are you saying it is not possible to have foo.py and foo/bar.py then import a function from foo.py? – David Williams Apr 26 '13 at 21:19
  • @DavidWilliams I've updated. The error you are seeing is due to the import order, even though my first answer is still relevant when you are dealing with modules/packages with the same name. – Bakuriu Apr 26 '13 at 21:28
  • 1
    I think actually we might be talking about slightly different things. Try this: `touch foo.py && mkdir foo && touch foo/__init__.py && touch foo/bar.py` create a class called Foo in foo.py and Bar in bar.py. Then try to import `$ python -c "from foo import Foo" Traceback (most recent call last): File "", line 1, in ImportError: cannot import name Foo` – David Williams Apr 26 '13 at 21:43
  • 2
    @DavidWilliams The code in your comment simply confirms what I state in my answer. The `foo` package is loaded and then it cannot find the name `Foo`. The answer to your question is that you *cannot* have `foo.py` and `foo/__init__.py` in the same directory and have a working `import`. – Bakuriu Apr 26 '13 at 21:51
  • 1
    Well, I understand, and accept. Kinda seems like a wart on Python. In *many* OO languages is common to have this file and directory setup for namespace purposes, but ok. – David Williams Apr 26 '13 at 21:53
  • @DavidWilliams I think the problem is that python `import` is completely different the the "import" of most other languages. For example in Java & co. it's pretty easy to understand if the name is the name of a class(hence a file) or of a package(hence a directory), and so this problem doesn't exist. I believe this choice was made because trying "smarter" semanthics would create much more side effects(e.g. modules aren't singleton anymore, or packages must become completely different objects etc.) – Bakuriu Apr 26 '13 at 21:57
4

I'm pretty sure this is not something you should do, but you can force Python to import specific file as a module using imp:

import imp

with open("foo.py") as source:
    foo = imp.load_module("foo", source, "./", ('', '', imp.PY_SOURCE))

now you can do:

gaz_instance = foo.gaz()
Jacek Przemieniecki
  • 5,757
  • 1
  • 12
  • 15
  • 1
    This works only assuming that the working directory is the same where `foo.py` is, but this may not be true, since the OP's `lib` directory could have been added to the `sys.path` in some way. To obtain the directory you should call `imp.find_module('foo')` and get extract the path to the file. I didn't add this to my answer because it is a big change in how `import` works and should only be used if required(e.g. dynamically loading a plug-in/extension at runtime). – Bakuriu Apr 26 '13 at 22:03
  • `imp.find_module('foo')` will return the info for package in /foo/ directory (assuming both foo.py and /foo/ are in the same dir) – Jacek Przemieniecki Apr 26 '13 at 22:18