4

This linked answer tells me how to import a single module with a dot in its name, but how do I import all modules from a package with a dot in its name:

from package.with.dot.in.name import *

where my files look something like:

package.with.dot.in.name/
    __init__.py
    module_1.py
    module_2.py

I know that having dots in a package name is wrong. It's there because Sikuli requires your "project" to be named "{project}.sikuli".

Community
  • 1
  • 1
Jace Browning
  • 11,699
  • 10
  • 66
  • 90
  • @DavidReeve that's the question I specifically mention in my question. It doesn't answer my question, because it talks about loading a single **module**. – Jace Browning Dec 18 '14 at 20:09
  • @PauloScardine my question **is not** a duplicate of the linked question. – Jace Browning Dec 18 '14 at 20:11
  • You can import packages using `imp.load_module`. You'd just have to reference them through the package name (`package_with_dot_in_name.function()`). See the documentation: https://docs.python.org/2/library/imp.html?highlight=imp#imp.load_module – David Reeve Dec 18 '14 at 20:23
  • 2
    You can't. You should import the individual modules instead. If you want a package with a functional `__init__.py` etc., don't put dots in the name of the directory. If you can't get Sikuli to work with that, ask a question *about Sikuli*. – Kevin Dec 18 '14 at 20:29

3 Answers3

2

Based on this answer and some of the comments, I was able to do:

name = 'package.with.dot.in.name'
pathname, description = imp.find_module(name)[1:]
package = imp.load_module(name, None, pathname, description)
locals().update(package.__dict__)
Community
  • 1
  • 1
Jace Browning
  • 11,699
  • 10
  • 66
  • 90
1

While in no way I would encourage this behavior, you can do this by updating your locals() via a reference to it with the internal dictionary of attributes from the module you imported:

>>> r = __import__('requests')
>>> l = locals()
>>> l.update(r.__dict__)
>>> locals()['cookies']
<module 'requests.cookies' from '/usr/local/lib/python2.7/site-packages/requests/cookies.pyc'>

Or, put another way:

>>> cookies
<module 'requests.cookies' from '/usr/local/lib/python2.7/site-packages/requests/cookies.pyc'>

Edit: using Jace's self-answer below, the following will work for filenames with dots:

name = 'package.with.dot.in.name'
pathname, description = imp.find_module(name)[1:]
package = imp.load_module(name, None, pathname, description)
locals().update(package.__dict__)
  • Won't `__import__('package.with.dot.in.name')` attempt to treat the dots as separators? – Jace Browning Dec 18 '14 at 21:04
  • I don't believe so, but I didn't have a module around to test with. As long as you're using _some process_ that will return a reference (e.g. ``, you can continue on with the rest of my answer) –  Dec 18 '14 at 21:06
0

Well, like almost everything in Python, the import system is hack-able. You just need to create a custom loader and register it at sys.meta_path (for details see PEP 302).

Lets say you want to hack the import system in order to load "foo.bar" if you import "foo_dot_bar":

# search folder "foo.bar" and load it as a package
from foo_dot_bar import *     

Be warned: this is just a starting point for you, it is not a fully tested solution; in fact it is way beyond my wizardry level!

# stupid_dot_importer.py
import os
import imp
import sys

class StupidDotPackageLoader(object):
    @staticmethod
    def _get_real_name(name):
        return ".".join(name.split('_dot_'))
    def find_module(self, name, path=None):
        try:
            imp.find_module(self._get_real_name(name))
        except ImportError:
            return None
        return self
    def load_module(self, name):
        _, pathname, description = imp.find_module(self._get_real_name(name))
        return imp.load_module(self._get_real_name(name), None, pathname, description)

Suppose you have the following structure:

foo.bar
   |
   +--- __init__.py 
   |
   +--- module1.py
   |
   +--- module2.py

And:

$ cat foo.bar/__init__.py
from module1 import *
from module2 import *

$ cat foo.bar/module1.py
foo = 'bar'

$ cat foo.bar/module2.py
spam = 'eggs'

Then magic:

>>> from stupid_dot_importer import *
>>> sys.meta_path = [StupidDotPackageLoader()]
>>> from foo_dot_bar import *
>>> foo
'bar'
>>> spam
'eggs'
>>>
Paulo Scardine
  • 73,447
  • 11
  • 124
  • 153