125

Basically there is a file called 8puzzle.py and I want to import the file into another file (in the same folder and I cannot change the file name as the file is provided). Is there anyway to do this in Python? I tried usual way from 8puzzle import *, it gives me an error.

Error is:

>>> import 8puzzle
  File "<input>", line 1
    import 8puzzle
           ^
SyntaxError: invalid syntax
>>> 
Simon Guo
  • 2,776
  • 4
  • 26
  • 35
  • 16
    Why do people say "it gives me [an] error" and then not post what the error is? – John Zwinck Feb 01 '12 at 02:56
  • 8
    @JohnZwinck It's a syntax error. I'm guessing because "8puzzle" isn't a valid identifier (it starts with a number), and the syntax for the import statement expects a Python identifier there. Which would make the answer "No, you can't. Rename the module to something that starts with a letter or an underscore." – millimoose Feb 01 '12 at 02:59
  • John made the good point, I will keep in mind. And thanks Abhijeet add the error message for me. Thanks. – Simon Guo Feb 01 '12 at 03:11
  • 2
    Rename `8puzzle.py` to `puzzle8.py` and use `import puzzle8`. – Bakuriu Aug 07 '16 at 12:14
  • See also http://stackoverflow.com/questions/6811902/import-arbitrary-named-file-as-a-python-module-without-generating-bytecode-file – tripleee Aug 24 '16 at 10:41
  • For people wondering: one use case is having filenames start with the date to structure a directory of one-off scripts (`20190911_test_foo.py`, `20190911_test_bar.py`, `20190911_some_class_used_for_foo_and_bar`). – oulenz Sep 11 '19 at 08:48

4 Answers4

146

You could do

puzzle = __import__('8puzzle')

Very interesting problem. I'll remember not to name anything with a number.

If you'd like to import * -- you should check out this question and answer.

Community
  • 1
  • 1
Yuji 'Tomita' Tomita
  • 115,817
  • 29
  • 282
  • 245
  • 1
    works great! thanks. yeah, I would not name it start with a number, but it is a course assignment handout file, so I cannot change the name. But it seems doesn't matter though as we already got the solution for it. Thanks again. – Simon Guo Feb 01 '12 at 03:08
  • 10
    Help save the world, or at least your classmates. If you get handed an impossible import, bring it to the instructor's attention. Yeah, sometimes they hate being wrong, but if you are having this problem, so is everyone else and although this answer works, it is not the right solution (unless the class is "Obfuscated Python 101"). – msw Feb 01 '12 at 03:40
  • 4
    A better way (with python 2.7 at least) is to use the 'importlib' module : puzzle = importlib.import_module('8puzzle') – Cédric Jan 08 '14 at 23:39
  • 5
    There is actually a good use case for this - as part of compiling/productionizing process, concatenating python modules together is easiest if they are named in lexigraphical form (generally it doesn't matter, but constants and imports at the top, 'if __name__' at bottom, so a few modules that start with '0' can be useful.) Also useful in debugging such an unusual directory layout, when combined with inotify or watch, something like: watch -n .1 'cat * | python', which would load your python app every tenth of a second (or at least as fast as possible), or: cat $(find . -name "*.py") | python – fatal_error Mar 17 '15 at 19:55
  • 3
    Late to the party, but another use case is importing from Alembic migrations, since they all start with random hashes – kevlarr Jan 17 '20 at 16:50
50

The above answers are correct, but as for now, the recommended way is to use import_module function:

importlib.import_module(name, package=None)
Import a module. The name argument specifies what module to import in absolute or relative terms (e.g. either pkg.mod or ..mod). If the name is specified in relative terms, then the package argument must be set to the name of the package which is to act as the anchor for resolving the package name (e.g. import_module('..mod', 'pkg.subpkg') will import pkg.mod).

The import_module() function acts as a simplifying wrapper around importlib.__import__(). This means all semantics of the function are derived from importlib.__import__(). The most important difference between these two functions is that import_module() returns the specified package or module (e.g. pkg.mod), while __import__() returns the top-level package or module (e.g. pkg).

If you are dynamically importing a module that was created since the interpreter began execution (e.g., created a Python source file), you may need to call invalidate_caches() in order for the new module to be noticed by the import system.

__import__ is not recommended now.

importlib.__import__(name, globals=None, locals=None, fromlist=(), level=0)
An implementation of the built-in __import__() function.

Note Programmatic importing of modules should use import_module() instead of this function.

laike9m
  • 18,344
  • 20
  • 107
  • 140
  • It does work thanks, but it doesn't work to import a function or variable inside one of these files starting with a number. If I do: `an_imported_file = importlib.import_module('13_file')`, then I can't do `from an_imported_file import var_x`. Is there anything that can be done to achieve this? – Martin May 29 '20 at 13:58
  • `/usr/local/bin/python3.7 "/Users/constan/Desktop/2_COData/1_PYTHON /CODEX/13_Spacy/children.py" Traceback (most recent call last): File "/Users/constan/Desktop/2_COData/1_PYTHON /CODEX/13_Spacy/children.py", line 7, in from an_imported_file import var_x ModuleNotFoundError: No module named 'an_imported_file'` – Martin Jun 01 '20 at 09:49
  • Also, the line ` from an_imported_file import var_x ` in Pycharm is underlined in red... – Martin Jun 01 '20 at 09:50
  • I don't know sorry. My general advice is to avoid doing this. – laike9m Jun 03 '20 at 06:08
  • 1
    @Martin Just use an_imported_file.var_x –  Jun 28 '21 at 09:03
  • @Martin I have the same question even though I have my own answer to it. I would try this. `an_imported_file = importlib.import_module('13_file'); var_x = an_imported_file.var_x` – KH Kim Aug 29 '21 at 05:54
  • @Martin yes, it should be no surprise that code that imports a file *dynamically*, by *checking the value of a string when it runs*, is not something that the IDE can sanity-check for correctness ahead of time. – Karl Knechtel Jan 13 '23 at 10:39
5

The file directory structure is as follows:

 daily
   -- 20210504
         permutations.py
         __init__.py
   __init__.py

You can import the permutations module by __import__ or importlib.import_module.

The official documentation recommends using importlib.import_module.

import(name, globals=None, locals=None, fromlist=(), level=0) -> module

Import a module. Because this function is meant for use by the Python interpreter and not for general use, it is better to useimportlib.import_module()to programmatically import a module.

What is the difference?

If implemented using __import__. For example:

res = __import__('daily.20210504.permutations')

The result of res is the daily module. daily module

So, if you want to get the permutations module, you need to provide the fromlist parameter, which is written as follows.

res = __import__('daily.20210504.permutations', fromlist=('daily.20210504'))

The result of res can be seen now as enter image description here That's the right result.

What if I use importlib.import_module?

res = importlib.import_module('daily.20210504.permutations')

this allows you to get the permutations module directly.

marie
  • 180
  • 1
  • 8
-1

Don't use the .py extension in your imports.

Does from 8puzzle import * work?

For what it's worth, from x import * is not a preferred Python pattern, as it bleeds that module's namespace into your current context.

In general, try to import things you specifically want from that module. Any global from the other module can be imported.

e.g., if you have 8puzzle.foo you could do `from 8puzzle import

Edit:

While my .py message is correct, it isn't sufficient.

The other poster's __import__('8puzzle') suggestion is correct. However, I highly recommend avoiding this pattern.

For one, it's reserved an internal, private Python method. You are basically breaking the fundamental assumptions of what it means to be able to import a module. Simply renaming the file to something else, like puzzle8, will remedy this.

This will frustrate the hell out of experienced Python programmers who are expecting to know what your imports are at the top and are expecting code to (try to) conform to PEP8.

Community
  • 1
  • 1
mvanveen
  • 9,754
  • 8
  • 33
  • 42
  • 1
    sorry about the confusing. What I did was `from 8puzzle import *` and I edited my original question. And it doesn't work as mvanveen said. – Simon Guo Feb 01 '12 at 03:05
  • That is my bad. I forgot that module filenames can't start witha number. I've posted an edit. – mvanveen Feb 01 '12 at 03:13