2

I have the following mis-fortunate situation:

Three directories (A, B and C) contain a python module M with a function F. (Those directories are not packages and it is impossible to change anything about the situation.)

I am looking for a way to import them separately to access their functionalities. How do I need to import those modules to access F somewhat like this:

A.F()
B.F()
C.F()
Woltan
  • 13,723
  • 15
  • 78
  • 104
  • 1
    user from a.M import F as A_F – timger Sep 14 '11 at 14:04
  • I'm curious about how you got into this f0rked up situation, why can't you solve it the 'proper' way and now have to hack something together? – wim Sep 14 '11 at 15:08
  • @wim The f0rked up situation is a dependency and you do not want to change things in a dependency or you will end up messing up the interface which leads to god knows what... This is why I am looking for a 'proper' way at least on my side of the interface. – Woltan Sep 15 '11 at 06:49
  • Duplicate of [How to import a module given the full path?](http://stackoverflow.com/questions/67631/) – Piotr Dobrogost Jan 22 '12 at 21:56

4 Answers4

4

This will work, but it seems a bit inelegant...

import sys

sys.path.append("A")
import M as A

sys.path.pop()
del sys.modules['M']

sys.path.append("B")
import M as B

and so on...
ed.
  • 1,373
  • 8
  • 10
  • IMO this is the way to go you just have to fix the fact that `pre_path` point always to `sys.path` so changing `sys.path` will change `pre_path`. What you should do is each time `pop()` from `sys.path` after you finish importing. – mouad Sep 14 '11 at 14:11
  • Somehow the module `M` in `B` is not loaded with `import M as B` if previously `import M as A` was imported. If I call `F` of `B` with `B.F()` actually the function `F` in `A` is called. – Woltan Sep 14 '11 at 14:13
  • ahh and you have also to delete `sys.modules['M']` after importing it, because the next time you try to import the other module `M` the import will be skipped because it's already in `sys.modules`. – mouad Sep 14 '11 at 14:14
  • Probably it's still in sys.modules as 'M' – MatthewWilkes Sep 14 '11 at 14:15
4

You need to exec things into a new locals dictionary. You can only get to the files you mention as files, not as modules, then stuff them into a moduletype.

from types import ModuleType

with open("A/M.py") as a:
    A = ModuleType('A')
    exec a.read() in A.__dict__

with open("B/M.py") as b:
    B = ModuleType('B')
    exec b.read() in B.__dict__

with open("C/M.py") as c:
    C = ModuleType('C')
    exec c.read() in C.__dict__

Then access them like B.F() as you wanted. The only problem is the module metadata isn't set up correctly, so it will appear as a builtin. You can even then do:

import sys
sys.modules['A'] = A
sys.modules['B'] = B
sys.modules['C'] = C

and they will be importable like import A from other parts of your application.

MatthewWilkes
  • 1,048
  • 8
  • 15
  • Added the sys.modules problem as an advantage to this method by explicitly setting the constructed modules in you can reimport. – MatthewWilkes Sep 14 '11 at 14:31
1

put an __init__.py in each A/ B/ and C/. The content of this file is

from M import F

Than the following code should work:

import A, B, C
A.F()
B.F()
C.F()

The __init__.py declares the directory as a package, and the statements in this file are executed when you import the package.

rocksportrocker
  • 7,251
  • 2
  • 31
  • 48
  • Thx for the reply, but as I said, I cannot change anything about how the directories look like. So no `__init__.py` can be added to make it a package. – Woltan Sep 14 '11 at 14:08
-2

use import as like

from A.M import F as A_F
timger
  • 944
  • 2
  • 13
  • 31
  • But then the `sys.path` would have to be set each time I import a module. Could you elaborate on that part? – Woltan Sep 14 '11 at 14:09
  • @Woltan sorry for my thoughtless you should add your directory to syspath use sys.path.append like the answer from rocksportrocker – timger Sep 14 '11 at 14:19