views:

288

answers:

5

Lets say I'm in a file called openid.py and I do :

from openid.consumer.discover import discover, DiscoveryFailure

I have the openid module on my pythonpath but the interpreter seems to be trying to use my openid.py file. How can I get the library version?

(Of course, something other than the obvious 'rename your file' answer would be nice).

+2  A: 

Rename it. This is the idea behind name spaces. your openid could be a sub-module in your top module project. your email will clash with top module email in stdlib.

because your openid is not universal, it provides a special case for your project.

SilentGhost
Actually, I think the idea behind name spaces is *not* to have to rename it to something unique ;) myproject.openid is something different than openid.With the new absolute imports, import openid will always get the system-wide (e.g. stdlib) module and the relative .openid will get the openid submodule in the current module.
Chris089
of course it isn't. **If** he his module `project` than he should be using `project.openid`. It's not clear why OP is doing what he's doing, but if he doesn't have module `project`, then he should rename `openid` to something else.
SilentGhost
correct. outside the package it is pkg.openid. But inside the "openid.py" file i can't get access to the "openid" library. That's the main problem.
Paul Tarjan
why the downvote?
SilentGhost
+1  A: 

You can use relative or absolute imports (depending on the specifics of your situation), which are covered in PEP 328 most recently. Of course, seriously, you should not be creating naming conflicts like this and should rename your file.

Nick Bastin
Even if the semantically correct name for the file is openid? Like if it is in a directory of types of aliases along with, email, webpage, domain, etc?
Paul Tarjan
@Paul: Even then. If it's in a "directory of types of aliases", then that really ought to be a package, and then it's pkg.openid, which is unambiguous.
Nick Bastin
correct. outside the package it is pkg.openid. But inside the "openid.py" file i can't get access to the "openid" library. That's the main problem.
Paul Tarjan
@Paul: sure you can. Use an absolute import (from __future__ import absolute_import) and do 'import openid', which will resolve as basically (pseudo-path-structure) /openid, instead of /pkg/openid.
Nick Bastin
+8  A: 

Thats the reason absolute imports have been chosen as the new default behaviour. However, they are not yet the default in 2.6 (maybe in 2.7...). You can get their behaviour now by importing them from the future:

from __future__ import absolute_import

You can find out more about this in the PEP metnioned by Nick or (easier to understand, I think) in the document "What's New in Python 2.5".

Chris089
A: 

You could try shuffling sys.path, to move the interesting directories to the front before doing the import.

ThomasH
Won't help if `sys.modules['openid']` is already set, as it would be in the OP's case as he's in `openid.py`.
Alex Martelli
@Alex Why would that be the case? Is the current file automatically added to sys.modules? A quick test.py < "import sys; print sys.modules.keys()", when run, suggests otherwise!?
ThomasH
A module that's _imported_ gets added to sys.modules under its real name; the one file that's run as the "main program" gets the conventional name of `__main__` instead. But if you're running that openid.py as the main module then there's no reason to have it on sys.path in the first place!
Alex Martelli
+2  A: 

I won't get into the polemics on renaming and instead focus on showing you how to do what you want (whether it's "good for you" or not;-). The solution is not difficult...

Just set __path__! A little demonstration:

$ mkdir /tmp/modules /tmp/packages
$ mkdir /tmp/packages/openid
$ echo 'print "Package!"' > /tmp/packages/openid/__init__.py
$ gvim /tmp/modules/openid.py
$ PYTHONPATH='/tmp/modules:/tmp/packages' python -c'import openid'
Module!
Package!

this shows a module openid managing to import a homonymous package even though the module's path comes earlier in sys.path, and sys.modules['openid'] is clearly already set at that time. And all the "secret" is in openid.py's simple code...:

print "Module!"
__path__ = ['/tmp/packages']
import openid

without the __path__ assignment, of course, it would only emit Module!.

Also works for importing submodules within the package, of course. Do:

$ echo 'print "Submod!"' > /tmp/packages/openid/submod.py

and change openid.py's last line to

from openid import submod

and you'll see:

$ PYTHONPATH='/tmp/modules:/tmp/packages' python -c'import openid'
Module!
Package!
Submod!
$
Alex Martelli
Regarding sys.modules['openid'] being set. You also said this in another comment, but I'm not so sure. Why would that be the case? Is the current file automatically added to sys.modules? A quick test.py < "import sys; print 'test' in sys.modules.keys()", when run, suggests otherwise!?
ThomasH
As I replied to the other comment: the one file that's run as the main module goes into `sys.modules['__main__']` instead (as its `__name__` is artificially and conventionally set to `__main__`). That's why I'm **import**ing openid here, to show that `__path__` still works. If all you need w/openid.py is to run it as main then there's no reason to have it in sys.path.
Alex Martelli
I thought that the OP's problem stems simply from the fact that '.' comes earlier in sys.path, so the current directory is searched for 'openid' where the importing openid.py script is found. But if you shift the 'interesting' directories of sys.path to its front, the other 'openid' (the module) is found first, and everything is fine.
ThomasH
It's extremely confusing (you and the OP both appear to do that sometimes) to refer to the _package_ openid as "the module" -- openid.py is the module, directory openid with a file `__init__.py` is the package. If openid.py is never imported, then hacking sys.path works; however, my answer works more generally (whether openid.py is imported or run as main script), _and_ avoids messing with system-global settings.
Alex Martelli
Thanks, got it. I will also try to improve on my wording :-).
ThomasH