13

Say there is a folder, '/home/user/temp/a40bd22344'. The name is completely random and changes in every iteration. I need to be able to import this folder in Python using a fixed name, say 'project'. I know I can add this folder to sys.path to enable import lookup, but is there a way to replace 'a40bd22344' with 'project'?

Maybe some clever hacks in init.py?

Added:

It needs to be global - that is, other scripts loading 'project' via the standard:

import project

Have to work properly, loading a40bd22344 instead.

2
  • 1
    Why can't you fix the process that created the temp file? It would be easier to fix this at the source instead of creating an elaborate work-around. What's wrong with fixing the name in /temp/ to be a real module name?
    – S.Lott
    Commented Jul 8, 2009 at 10:01
  • 1
    It's beyond of my control, folders are created by CI server.
    – Art
    Commented Nov 27, 2009 at 2:18

3 Answers 3

25

Here's one way to do it, without touching sys.path, using the imp module in Python:

import imp
f, filename, desc = imp.find_module('a40bd22344', ['/home/user/temp/'])
project = imp.load_module('a40bd22344', f, filename, desc)
project.some_func()

Here is a link to some good documentation on the imp module:

1
  • 1
    This doesn't touch sys.path but I think using imp causes the package to be reloaded every time this code is executed. I'd prefer Alex's solution because it does the right thing even if executed multiple times.
    – Jon-Eric
    Commented Nov 17, 2009 at 15:29
19

You first import it with import:

>>> __import__('temp/a40bd22344')
<module 'temp/a40bd22344' from 'temp/a40bd22344/__init__.py'>

Then you make sure that this module gets known to Python as project:

>>> import sys
>>> sys.modules['project'] = sys.modules.pop('temp/a40bd22344')

After this, anything importing project in the current Python session will get the original module

>>> import project
>>> project
<module 'temp/a40bd22344' from 'temp/a40bd22344/__init__.py'>

This will work also for sub-modules: if you have a foobar.py in the same location you'll get

>>> import project.foobar
>>> project.foobar
<module 'project.foobar' from 'temp/a40bd22344/foobar.py'>

Addendum. Here's what I'm running:

>>> print sys.version
2.5.2 (r252:60911, Jul 31 2008, 17:28:52) 
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)]
4
  • 1
    Excellent, except for the little detail that it does not work: in Python 2.6 and 3.1 it says "ImportError: Import by filename is not supported.", in 2.5 just "ImportError: No module named temp/a40bd22344", on the import (just tried all three on my Mac to confirm I hadn't forgotten how import works!-). I assume it works on your platform, krawyoti, and yours, Art, or you wouldn't have marked it as accepted, so I'm curious: what platforms are those? Commented Jul 8, 2009 at 14:03
  • Well it stands to reason that this loophole in import I was using was fixed. Lazy of me not to try it in Python 2.6 too.
    – krawyoti
    Commented Jul 8, 2009 at 15:35
  • Alex, worked for me. Ubuntu/python 2.5/2.6. You need to use full path in import, or alternatively, add it to sys.path and then call import just on folder name
    – Art
    Commented Jul 9, 2009 at 3:49
  • 3
    You may want to set the module's __name__ attribute as well, so that code inspecting it will see it as the same as code which looks at sys.modules.
    – Glyph
    Commented Jul 9, 2009 at 11:22
17

Sure, project = __import__('a40bd22344') after sys.path is set properly will just work.

Suppose you want to do it in a function taking the full path as an argument and setting the global import of project properly (as well as magically making import project work afterwards in other modules). Piece of cake:

def weirdimport(fullpath):
  global project
  import os
  import sys
  sys.path.append(os.path.dirname(fullpath))
  try:
      project = __import__(os.path.basename(fullpath))
      sys.modules['project'] = project
  finally:
      del sys.path[-1]

this also leaves sys.path as it found it.

3
  • I've just added a clarification to my question, will it work in this case as well?
    – Art
    Commented Jul 8, 2009 at 8:43
  • 1
    Alex, put the import statement in a try..finally bracket, so as to ensure that sys.path is always correctly restored.
    – krawyoti
    Commented Jul 8, 2009 at 10:05
  • 1
    @Art, as @krawyoti says that's accomplished by sticking it in sys.modules[project] as @krawyoti says. @krawyoti, good advice -- let me edit to reflect these two changes. Commented Jul 8, 2009 at 13:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.