Given a package, how can I automatically find all its sub-packages?
+4
A:
You can't rely on introspection of loaded modules, because sub-packages may not have been loaded. You'll have to look at the filesystem, assuming the top level package in question is not an egg, zip file, extension module, or loaded from memory.
def get_subpackages(module):
dir = os.path.dirname(module.__file__)
def is_package(d):
d = os.path.join(dir, d)
return os.path.isdir(d) and glob.glob(os.path.join(d, '__init__.py*'))
return filter(is_package, os.listdir(dir))
James Emerton
2009-05-06 22:11:51
Not working. That glob.glob thing returns a list: Is that a mistake?
cool-RR
2009-05-06 22:16:10
works just fine.
SilentGhost
2009-05-06 22:31:42
I had forgotten that os.listdir does not return the full path. Fixed the bug. (An empty list in a boolean context evaluates to false.)
James Emerton
2009-05-06 22:33:56
SilentGhost tells me that my implementation is terrible, though it works for me. I'm assuming yours is okay, so I guess I'll select that as the answer. However, you think it's okay to put the question mark after the `py`? Wouldn't it not work when there isn't a `pyc` or `pyo` file?
cool-RR
2009-05-06 22:40:28
You're correct, it should be an asterisk so that it matches .py, .pyc, and .pyo files. As it stands, there are still a lot of gotchas with this sort of thing. I hope you aren't using it for anything important, like missile control. =)
James Emerton
2009-05-06 22:50:40
+1 for the warning to missile control operators :-)
Jarret Hardie
2009-05-06 23:37:49
A:
Inspired by James Emerton's answer:
def find_subpackages(module):
result=[]
for thing in os.listdir(os.path.dirname(module.__file__)):
full=os.path.join(os.path.dirname(module.__file__),thing)
if os.path.isdir(full):
if glob.glob(os.path.join(full, '__init__.py*'))!=[]:
result.append(thing)
return result
cool-RR
2009-05-06 22:32:25