Module name to filename and back?

Ron Adam rrr at ronadam.com
Thu Jan 18 23:12:17 CET 2007


Ron Adam wrote:
> Is there a function to find a filename from a dotted module (or package) name 
> without importing it?
> 
> The imp function find_module() doesn't work with dotted file names.  And it 
> looks like it may import the file as it raises an ImportError error exception if 
>   it can't find the module. (Shouldn't it raise an IOError instead?)
> 
> What I'm looking for is to be able to get the full module name when I have a 
> filename.  And get the full filename when I have the module name.  And do both 
> of these without importing the module.
> 
>     modulename <==> filename
>     filename <==> modulename

I found a partial answer in trace.py.  It has a fullmodname() function, but it 
doesn't do any validation so the name it returns is a guess.  Starting with it I 
tried to make it a bit more complete, but it still needs work.  Seems like there 
should be an easier way.

Ron



def importname(path):
     """ Get module or package name from a path name.

         Return None if path is invalid, or name is not a
         valid (reachable) package or module.

     """
     path = os.path.normcase(path)
     if not os.path.exists(path):
         return
     if path.endswith(os.sep):
         path = path[:-1]
     longest = ""
     for dir in sys.path:
         dir = os.path.normcase(dir) + os.sep
         if path.startswith(dir):
             if len(dir) > len(longest):
                 longest = dir
     if longest:
         base = path[len(longest):]
     else:
         # should check if in current dir?
         return   # path not in search sys.path

     # This need a bit more work, it should also check
     # for valid parent packages too.
     if os.path.isdir(path):
         valid = False
         for ext in ['.py', '.pyc', '.pyo']:
             if os.path.isfile(os.path.join(path, '__init__' + ext)):
                 valid = True
                 break
         else:
             return

     base, ext = os.path.splitext(base)
     name = base.replace(os.sep, ".")
     if os.altsep:
         name = name.replace(os.altsep, ".")
     return name


path = "c:\\python25\\lib\\xml\\sax\\handler.py"
print importname(path)

prints --> xml.sax.handler





More information about the Python-list mailing list