Yields ModuleInfo for all modules recursively on path, or, if path is None, all accessible modules. 'path' should be either None or a list of paths to look for modules in. 'prefix' is a string to output on the front of every module name on output. Note that this function m
(path=None, prefix='', onerror=None)
| 35 | |
| 36 | |
| 37 | def walk_packages(path=None, prefix='', onerror=None): |
| 38 | """Yields ModuleInfo for all modules recursively |
| 39 | on path, or, if path is None, all accessible modules. |
| 40 | |
| 41 | 'path' should be either None or a list of paths to look for |
| 42 | modules in. |
| 43 | |
| 44 | 'prefix' is a string to output on the front of every module name |
| 45 | on output. |
| 46 | |
| 47 | Note that this function must import all *packages* (NOT all |
| 48 | modules!) on the given path, in order to access the __path__ |
| 49 | attribute to find submodules. |
| 50 | |
| 51 | 'onerror' is a function which gets called with one argument (the |
| 52 | name of the package which was being imported) if any exception |
| 53 | occurs while trying to import a package. If no onerror function is |
| 54 | supplied, ImportErrors are caught and ignored, while all other |
| 55 | exceptions are propagated, terminating the search. |
| 56 | |
| 57 | Examples: |
| 58 | |
| 59 | # list all modules python can access |
| 60 | walk_packages() |
| 61 | |
| 62 | # list all submodules of ctypes |
| 63 | walk_packages(ctypes.__path__, ctypes.__name__+'.') |
| 64 | """ |
| 65 | |
| 66 | def seen(p, m={}): |
| 67 | if p in m: |
| 68 | return True |
| 69 | m[p] = True |
| 70 | |
| 71 | for info in iter_modules(path, prefix): |
| 72 | yield info |
| 73 | |
| 74 | if info.ispkg: |
| 75 | try: |
| 76 | __import__(info.name) |
| 77 | except ImportError: |
| 78 | if onerror is not None: |
| 79 | onerror(info.name) |
| 80 | except Exception: |
| 81 | if onerror is not None: |
| 82 | onerror(info.name) |
| 83 | else: |
| 84 | raise |
| 85 | else: |
| 86 | path = getattr(sys.modules[info.name], '__path__', None) or [] |
| 87 | |
| 88 | # don't traverse path items we've seen before |
| 89 | path = [p for p in path if not seen(p)] |
| 90 | |
| 91 | yield from walk_packages(path, info.name+'.', onerror) |
| 92 | |
| 93 | |
| 94 | def iter_modules(path=None, prefix=''): |
searching dependent graphs…