285

I want to import foo-bar.py. This works:

foobar = __import__("foo-bar")

This does not:

from "foo-bar" import *

My question: Is there any way that I can use the above format i.e., from "foo-bar" import * to import a module that has a - in it?

martineau
  • 112,593
  • 23
  • 157
  • 280
Bala
  • 3,338
  • 3
  • 18
  • 17
  • 13
    Why do you have a module with a dash in its name? – Matti Virkkunen Dec 02 '11 at 02:00
  • 30
    I'm guessing it was originally written as a script rather than as a module. – Michael Hoffman Dec 02 '11 at 02:19
  • 3
    possible duplicate of [Python Module with a dash, or hyphen (-) in its name](http://stackoverflow.com/questions/7583652/python-module-with-a-dash-or-hyphen-in-its-name) – Piotr Dobrogost Feb 26 '14 at 14:40
  • @MattiVirkkunen makepy.py of win32com will generate module with dash in it. too bad. comtypes solved this by converting it to underscore – swdev Apr 11 '14 at 01:45
  • 5
    @MattiVirkkunen I think Python should not limit the names I can give my directories. It is not its responsibility to do so. – Zelphir Kaltstahl Nov 11 '16 at 12:34
  • @Zelphir: Do you also think Python should not limit the names you can give your variables and other identifiers? Surely you can see why it's silly to name a module (whose name is defined by the directory name) something that's not a valid identifier. – Matti Virkkunen Nov 14 '16 at 05:50
  • @MattiVirkkunen Actually I think variables are something inside Python and thus its "task" to care for, so that's OK. But maybe you have a point there about modules being its part as well. Anyway, it's not a big issue, just something one needs to know : ) – Zelphir Kaltstahl Nov 14 '16 at 09:20
  • 1
    Possible duplicate of [Is it ok to use dashes in Python files when trying to import them?](http://stackoverflow.com/questions/761519/is-it-ok-to-use-dashes-in-python-files-when-trying-to-import-them) – maxkoryukov May 17 '17 at 04:31

7 Answers7

185

Starting from Python 3.1, you can use importlib :

import importlib  
foobar = importlib.import_module("foo-bar")

( https://docs.python.org/3/library/importlib.html )

Julien
  • 2,130
  • 1
  • 10
  • 17
144

you can't. foo-bar is not an identifier. rename the file to foo_bar.py

Edit: If import is not your goal (as in: you don't care what happens with sys.modules, you don't need it to import itself), just getting all of the file's globals into your own scope, you can use execfile

# contents of foo-bar.py
baz = 'quux'
>>> execfile('foo-bar.py')
>>> baz
'quux'
>>> 
SingleNegationElimination
  • 144,899
  • 31
  • 254
  • 294
  • 33
    Python 3.x [What’s New In Python 3.0](https://docs.python.org/3/whatsnew/3.0.html) Removed execfile(). Instead of `execfile(fn)` use `exec(open(fn).read())` Also there is package importlib. – DevPlayer Apr 08 '15 at 14:26
  • 1
    "*if you don't care what happens with sys.modules*", can you clarify what you meant? What is the condition for using `execfile`? – mins May 18 '21 at 09:25
128

If you can't rename the module to match Python naming conventions, create a new module to act as an intermediary:

 ---- foo_proxy.py ----
 tmp = __import__('foo-bar')
 globals().update(vars(tmp))

 ---- main.py ----
 from foo_proxy import * 
Raymond Hettinger
  • 199,887
  • 59
  • 344
  • 454
  • 38
    I would never implement this. But I can't not give +1 for the sheer brilliance of this hack – inspectorG4dget Dec 02 '11 at 02:25
  • 14
    you could actually do this without the `foo_proxy.py` file, assign the output of `__import__(...)` to `sys.modules['foo_proxy']`. Actually, don't do that, it's a terrible idea. – SingleNegationElimination Dec 02 '11 at 14:03
  • 5
    Cool just what I was looking for. There is a usecase, if one uses native libraries which are shipped with a distribution. – Sven May 08 '13 at 14:59
50

If you can't rename the original file, you could also use a symlink:

ln -s foo-bar.py foo_bar.py

Then you can just:

from foo_bar import *
gitaarik
  • 36,986
  • 11
  • 91
  • 97
10

Like other said you can't use the "-" in python naming, there are many workarounds, one such workaround which would be useful if you had to add multiple modules from a path is using sys.path

For example if your structure is like this:

foo-bar
├── barfoo.py
└── __init__.py

import sys
sys.path.append('foo-bar')

import barfoo
Reda Drissi
  • 1,262
  • 2
  • 16
  • 29
0

in Python 3.6 I had the same problem "invalid syntax" when directly

import 'jaro-winkler' as jw

said "No module named 'jaro-winkler'" when using:

jw = __import__('jaro-winkler')

and importlib.import_module() same.

finally i use pip uninstall the jaro-winkler module...just FYI

Hassen Ch.
  • 1,584
  • 15
  • 31
kk120120
  • 11
  • 2
0

This was my scenario: I have a python library cloned in a git submodule which has a dash in its name:

|- python-my-lib
| `- mylib.py
`- my-script.py

It took me a long time to figure out the equivalent of:

# Do NOT use this!
sys.path.insert(1, './my-lib')
from mylib import MyClass

Appending the path is not an option, as it would only work if you run the script within the same directory. If you do /home/user/bin/my-script.py, this will fail.

This is the solution:

import importlib
mylib_module = importlib.import_module("python-my-lib.mylib")
MyClass = mylib_module.MyClass

Feel free to further improve this solution, if you know a simpler solution.

NicoHood
  • 136
  • 1
  • 6