views:

207

answers:

3

For instance, I want to make a sql alchemy plugin for another project. And I want to name that module sqlalchemy.py. The problem with this is that it prevents me from importing sqlalchemy:

#sqlalchemy.py
import sqlalchemy

This will make the module import itself. I've tried this, but it doesn't seem to work:

import sys
#Remove the current directory from the front of sys.path
if not sys.path[0]:
    sys.path.pop(0)
import sqlalchemy

Any suggestions?

+1  A: 

Don't name it sqlalchemy.py ?

Seriously. I think this is the problem absolute imports is supposed to solve. In python 2.5 it should not happen, but I could be wrong

Stefano Borini
I could do that, but the project dynamically loads plugins by module name. Not preferable, but it's a bit out of my hands.
Jason Baker
It happens under Python 2.6.4. I haven't tried it in other versions.
Jason Baker
+1  A: 

You may just be getting burned by differences between running code in the interactive interpreter and from a file. Remove the test for sys.path[0] being empty (when run from a file, it isn't) and the import should now work as you want.

$ more sqlalchemy.py
import sys
print sys.path[0]
sys.path.pop(0)
import sqlalchemy
print sqlalchemy.__file__
$ python sqlalchemy.py 
/Users/nad
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/sqlalchemy/__init__.pyc
$ python
Python 2.6.4 (r264:75706, Oct 28 2009, 20:34:51) 
[GCC 4.0.1 (Apple Inc. build 5493)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys; print repr(sys.path[0])
''

EDIT: the above applies if your main module is sqlalchemy.py. If your module is imported by another module, you'll also have to alter sys.modules as Alex explains.

Ned Deily
+5  A: 

Edit: as the OP has now mentioned that the issue is one of relative import being preferred to absolute, the simplest solution for the OP's specific problem is to add at the start of the module from __future__ import absolute_import which changes that "preference"/ordering.

The following still applies to the ticklish issue of two clashing absolute imports (which doesn't appear to be what the OP is currently facing...):

Once you've imported a module named x, that module's recorded in sys.modules['x'] -- changing sys.path as you're doing won't alter sys.modules. You'll also need to alter sys.modules directly.

E.g., consider:

$ cat a/foo.py
print __file__; import sys; sys.path.insert(0, "b"); del sys.modules["foo"]; import foo
$ cat b/foo.py
print __file__
$ python2.5 -c'import sys; sys.path.insert(0, "a"); import foo'
a/foo.py
b/foo.py

(running again will use and show the .pyc files instead of the .py ones of course).

Not the cleanest approach, and of course this way the original foo module is, inevitably, not accessible from the outside any more (since its sys.modules entry has been displaced), but you could play further fragile tricks as needed (stash sys.modules["foo"] somewhere before deleting it, after you import the other foo put that module somewhere else and reinstate the original sys.modules["foo"] -- etc, etc), depending on your exact needs. (Of course, avoiding the name clashes in the first place would almost invariably be simpler than waltzing all around them in this way;-).

Alex Martelli
Actually, `sys.modules['sqlalchemy']` points to the real sqlalchemy. `sys.modules['storm.databases.sqlalchemy']` points to my module. It just so happens that Python seems to choose the relative import over the absolute import.
Jason Baker
@Jason, yes, unless you `from __future__ import absolute_import`, which is the simplest solution when the issue is one of relative vs absolute imports (my answer is still recommended for conflicting absolute imports). Let me edit the answer accordingly.
Alex Martelli
Sorry, I should have been more clear in my question. :-) What version of Python is that `__future__` import compatible with?
Jason Baker