views:

151

answers:

4

I can check for a module in Python doing something like:

try:
  import some_module
except ImportError:
  print "No some_module!"

But I don't want to use try/except. Is there a way to accomplish this? (it should work on Python 2.5.x.)

Note: The reason for no using try/except is arbitrary, it is just because I want to know if there is a way to test this without using exceptions.

A: 

All methods of importing modules raise exceptions when called. You could try searching the filesystem yourself first for the file, but there are many things to consider.

Not sure why you don't want to use try/except though. It is the best solution, far better than the one I provided. Maybe you should clarify that first, because you probably have an invalid reason for not using try/except.

nosklo
If 'some_module' doesn't exist, this program gives an exception:Traceback (most recent call last): File "<stdin>", line 1, in <module>ImportError: No module named asasasa
BlogueroConnor
@Bloguero, that's exactly why one puts a try/except around statements which may fail in predictable ways (and for whose failure workarounds exist -- or for which special remedies are needed -- etc etc). In the immortal words of Commodore Grace Murray Hopper, "it's easier to ask forgiveness than permission";-).
Alex Martelli
A: 

sys.modules dictionary seems to contain the info you need.

Rado
hm, it does not
nosklo
This only contains modules that have already been imported: http://docs.python.org/library/sys.html#sys.modules
Rodrigo Queiro
+1  A: 

You can read here about how Python locates and imports modules. If you wanted to, you could replicate this logic in python, searching through sys.modules, sys.meta_path & sys.path to look for the required module.

However, predicting whether it would parse successfully (taking into account compiled binary modules) without using exception handling would be very difficult, I imagine!

Rodrigo Queiro
@Rodrigo, see my answer below -- not "very difficult" I hope (the given fake-hook only triggers on the fake 'GIVINGUP!' path item which is appended to the end of sys.path and thereby only tried if every other attempt to locate the module has already failed...).
Alex Martelli
I have already upvoted your answer! It is very clever, and works around re-implementing the import logic that I thought would be necessary.
Rodrigo Queiro
+5  A: 

It takes trickery to perform the request (and one raise statement is in fact inevitable because it's the one and only way specified in the PEP 302 for an import hook to say "I don't deal with this path item"!), but the following would avoid any try/except:

import sys

sentinel = object()

class FakeLoader(object):
  def find_module(self, fullname, path=None):
    return self
  def load_module(*_):
    return sentinel

def fakeHook(apath):
  if apath == 'GIVINGUP!!!':
    return FakeLoader()
  raise ImportError

sys.path.append('GIVINGUP!!!')
sys.path_hooks.append(fakeHook)

def isModuleOK(modulename):
  result = __import__(modulename)
  return result is not sentinel

print 'sys', isModuleOK('sys')
print 'Cookie', isModuleOK('Cookie')
print 'nonexistent', isModuleOK('nonexistent')

This prints:

sys True
Cookie True
nonexistent False

Of course, these would be absurd lengths to go to in real life for the pointless purpose of avoiding a perfectly normal try/except, but they seem to satisfy the request as posed (and can hopefully prompt Python-wizards wannabes to start their own research -- finding out exactly how and why all of this code does work as required is in fact instructive, which is why for once I'm not offering detailed explanations and URLs;-).

Alex Martelli