8

I'm trying to import a few classes from a module in another level. I can type all the classes, but I' trying to do it dynamically

if I do:

from ..previous_level.module import *
    raise: SyntaxError: import * only allowed at module level

the same from myapp folder:

from myapp.previous_level.module import *
    raise: SyntaxError: import * only allowed at module level

So I thought:

my_classes = ['Class_Foo', 'Class_Bar']
for i in my_classes:
    from ..previous_level.module import i
        raise: ImportError: cannot import name 'i'

and also:

my_classes = ['Class_Foo', 'Class_Bar']
for i in my_classes:
    __import__('myapp').previous_level.module.y
    raise: AttributeError: module 'myapp.previous_level.module' has no attribute 'y'

I've tried string format , getattr() , __getattr__ but no success.

It's impossible to do import this way, or I'm doing something wrong?

user5617880
  • 125
  • 1
  • 1
  • 8
  • If you need to do this, I think you are likely solving your problem in a wrong way. You are mixing data and code: usually _what your variables are_ should not be dynamic -- how will you use the dynamically imported variables? A dictionary may be a better fit. What are you actually trying to do? – RemcoGerlich Sep 06 '16 at 07:33
  • Anyway, it is possible to just import `..previous_level.module` and then get the classes from it with `getattr(module, classname)`. Modules are namespaces and they already function somewhat like dictionaries. – RemcoGerlich Sep 06 '16 at 07:34
  • Thanks ;) I'm mostly trying to learn a dynamic way to import some modules, not a real script – user5617880 Sep 06 '16 at 19:57

1 Answers1

10

The error SyntaxError: import * only allowed at module level happens if you try to import * from within a function. This is not visible from the question, but it seems that the original code was simething like:

def func():
    from ..previous_level.module import *  # SyntaxError

On the other hand, importing at the beginning of a module would be valid:

from ..previous_level.module import *      # OK

That said, I would still suggest using absolute imports without *:

from myapp.previous_level.module import ClassA, ClassB, ClassC

x = ClassA()

# or:

import myapp.previous_level.module

x = myapp.previous_level.module.ClassA()

BTW, this is completely wrong:

for i in my_classes:
    from ..previous_level.module import i
zvone
  • 18,045
  • 3
  • 49
  • 77
  • assuming the list of imports was very long, I think it would not always be sensible to list all classes. A submodule import might be a better option, ie `from myapp.previous_level import module` – M.T Sep 06 '16 at 08:38
  • @zvone thanks for the clarification, the major bug resides importing from inside a function, now I understand that. But there's any way to call functions using a 'for cycle' ? – user5617880 Sep 06 '16 at 08:50
  • @M.T I've tried to import 1st the module, then `from module import *` but raises the same `SyntaxError:` ... more tips ? Thanks ;) – user5617880 Sep 06 '16 at 08:54
  • You can import the functions you want at the top as @zvone mentioned. Then have `for func in (function1, function2, ...): func(*args, **kwargs)` if you really want to. – Steven Summers Sep 06 '16 at 10:36
  • Thank you. It's just for educational purpose, don't be afraid lol ;) – user5617880 Sep 06 '16 at 19:59