Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Import Class With Same Name as Directory [duplicate]

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
like image 696
David Williams Avatar asked Apr 26 '13 20:04

David Williams


2 Answers

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.

like image 164
Bakuriu Avatar answered Oct 04 '22 17:10

Bakuriu


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()
like image 22
Jacek Przemieniecki Avatar answered Oct 04 '22 18:10

Jacek Przemieniecki