1

Suppose I have a module package containing the following files. An empty file C:\codes\package\__init__.py and some non-trivial files:

One located in C:\codes\package\first.py

def f():
    print 'a'

Another located in C:\codes\package\second.py

def f():
    print 'b'

There is also a third file: C:\codes\package\general.py with the following code

def myPrint(module_name):
    module = __import__(module_name)
    module.f()

if __name__ == '__main__':
    myPrint('first')
    myPrint('second')

When I run the latter file, everything goes fine. However, if I try to execute the file C:\codes\test.py containing

if __name__ == '__main__':
    from package import general
    general.myPrint('first')
    general.myPrint('second')

I get the import error ImportError: No module named first. How to resolve this issue?

1

3 Answers 3

4

First, I suspect you forgot to metion you have a (possibly empty) file package\__init__.py which makes package a package. Otherwise, from package import general wouldn't work.

The second case differs from the first in so far as you are in a package. From inside a package, you wouldn't do import first, but import .first. The equivalent to the latter is described here where you either add level=1 as a parameter or (but I am not sure about that) you put .first into the string and set level to -1 (if it isn't the default nevertheless, that's not clear from the documentation).

Additionally, you have to provide at least globals(), so the right line is

module = __import__(module_name, globals(), level=1)

I have found this solution here.

Sign up to request clarification or add additional context in comments.

11 Comments

I don't think OP forgot to add __init__.py because from package import general works for him
As I said: he just forgot to mention the file.
@Daniil: as glglgl rightfully noticed, indeed I've added it but forgot to mention.
Thanks for the answer, so in import I shall do __import('.' + moduleName)?
@Ulysses Try it - but probably __import__(modulename, level=1) will work better.
|
0

In your case, you should import your module_name from package. Use fromlist argument:

getattr(__import__("package", fromlist=[module_name]), module_name)

2 Comments

And if someone renames the package? Better would be to do a relative import.
@glglgl I am not sure that it's possible to use relative pathes in __import__
0

Assuming, you're using Python 3, that's just because this version dropped the support for implicit relative imports. With Python 2 it would be working just fine.

So either you'd need to use relative imports in C:\codes\package\general.py, which would result in erroneous call to it, or add your package to the path. A little dirty, but working hack would be:

def myPrint(module_name):
    pkg = os.path.dirname(__file__)
    sys.path.insert(0, pkg)
    try:
        module = __import__(module_name)
    except:
        raise
    finally:
        sys.path.remove(pkg)
    module.f()

Maybe you can achieve a cleaner implementation with the importlib module.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.