from pydoc import ModuleScanner import warnings def scan_modules(): """Scans for available modules using pydoc.ModuleScanner, taken from help('modules')""" modules = {} def callback(path, modname, desc, modules=modules): if modname and modname[-9:] == ".__init__": modname = modname[:-9] + " (package)" if modname.find(".") < 0: modules[modname] = 1 def onerror(modname): callback(None, modname, None) with warnings.catch_warnings(): warnings.simplefilter("ignore") # ignore warnings from importing deprecated modules ModuleScanner().run(callback, onerror=onerror) return modules modules = list(scan_modules().keys()) print(sorted(modules)) from pydoc import ModuleScanner import warnings def scan_modules(): """Scans for available modules using pydoc.ModuleScanner, taken from help('modules')""" modules = {} def callback(path, modname, desc, modules=modules): if modname and modname[-9:] == ".__init__": modname = modname[:-9] + " (package)" if modname.find(".") < 0: modules[modname] = 1 def onerror(modname): callback(None, modname, None) with warnings.catch_warnings(): warnings.simplefilter("ignore") # ignore warnings from importing deprecated modules ModuleScanner().run(callback, onerror=onerror) return modules modules = list(scan_modules().keys()) print(modules) from pydoc import ModuleScanner import warnings def scan_modules(): """Scans for available modules using pydoc.ModuleScanner, taken from help('modules')""" modules = {} def callback(path, modname, desc, modules=modules): if modname and modname[-9:] == ".__init__": modname = modname[:-9] + " (package)" if modname.find(".") < 0: modules[modname] = 1 def onerror(modname): callback(None, modname, None) with warnings.catch_warnings(): warnings.simplefilter("ignore") # ignore warnings from importing deprecated modules ModuleScanner().run(callback, onerror=onerror) return modules modules = list(scan_modules().keys()) print(sorted(modules)) If you need all available modules, not just the ones that are present as files in all the directories in your sys.path, then you can use (the undocumented) pydoc.ModuleScanner (which unfortunately loads the modules to work):
from pydoc import ModuleScanner import warnings def scan_modules(): """Scans for available modules using pydoc.ModuleScanner, taken from help('modules')""" modules = {} def callback(path, modname, desc, modules=modules): if modname and modname[-9:] == ".__init__": modname = modname[:-9] + " (package)" if modname.find(".") < 0: modules[modname] = 1 def onerror(modname): callback(None, modname, None) with warnings.catch_warnings(): warnings.simplefilter("ignore") # ignore warnings from importing deprecated modules ModuleScanner().run(callback, onerror=onerror) return modules modules = list(scan_modules().keys()) print(modules) If you need all available modules, not just the ones that are present as files in all the directories in your sys.path, then you can use (the undocumented) pydoc.ModuleScanner:
from pydoc import ModuleScanner def scan_modules(): """Scans for available modules using pydoc.ModuleScanner, taken from help('modules')""" modules = {} def callback(path, modname, desc, modules=modules): if modname and modname[-9:] == ".__init__": modname = modname[:-9] + " (package)" if modname.find(".") < 0: modules[modname] = 1 def onerror(modname): callback(None, modname, None) ModuleScanner().run(callback, onerror=onerror) return modules modules = list(scan_modules().keys()) If you need all available modules, not just the ones that are present as files in all the directories in your sys.path, then you can use (the undocumented) pydoc.ModuleScanner (which unfortunately loads the modules to work):
from pydoc import ModuleScanner import warnings def scan_modules(): """Scans for available modules using pydoc.ModuleScanner, taken from help('modules')""" modules = {} def callback(path, modname, desc, modules=modules): if modname and modname[-9:] == ".__init__": modname = modname[:-9] + " (package)" if modname.find(".") < 0: modules[modname] = 1 def onerror(modname): callback(None, modname, None) with warnings.catch_warnings(): warnings.simplefilter("ignore") # ignore warnings from importing deprecated modules ModuleScanner().run(callback, onerror=onerror) return modules modules = list(scan_modules().keys()) print(modules) Use pkgutil.iter_modules to getIf you need all theavailable modules, not just the ones that are present as files in all the directories in your sys.path, then you can use (the undocumented) pydoc.ModuleScanner to get the rest:
import pkgutil from pydoc import ModuleScanner def scan_modules(): """Scans for available modules using pydoc.ModuleScanner, taken from help('modules')""" modules = {} def callback(path, modname, desc, modules=modules): if modname and modname[-9:] == ".__init__": modname = modname[:-9] + " (package)" if modname.find(".") < 0: modules[modname] = 1 def onerror(modname): callback(None, modname, None) ModuleScanner().run(callback, onerror=onerror) return modules modules_with_filesmodules = list(pkgutil.iter_modules()) other_modules = scan_modules() module_names = [m.name for m in modules_with_files] + list(other_modules.keys()) print(module_names) The problem with pkgutil.iter_modules is that it doesn't return all packages, only the ones that are files or directories, but CPython loads a few modules in other special ways that can't be detected by just looking at the files.
The problem with ModuleScanner is that it returns all available modules, including the ones you've pip installed. If you only need the packages that come with Python, then you can start Python with the -I command line option.
Here are the packages that pkgutil doesn't find on Python 3.9:
$ python3.9 -I Python 3.9.0+ (default, Oct 19 2020, 09:51:18) [GCC 10.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> modules = ... # paste the above code ... >>> import pkgutil >>> sorted(set(modules) - {m.name for m in pkgutil.iter_modules()}) ['_abc', '_ast', '_bisect', '_blake2', '_codecs', '_collections', '_csv', '_datetime', '_elementtree', '_functools', '_heapq', '_imp', '_io', '_locale', '_md5', '_operator', '_peg_parser', '_pickle', '_posixsubprocess', '_random', '_sha1', '_sha256', '_sha3', '_sha512', '_signal', '_socket', '_sre', '_stat', '_statistics', '_string', '_struct', '_symtable', '_thread', '_tracemalloc', '_warnings', '_weakref', 'array', 'atexit', 'binascii', 'builtins', 'cmath', 'errno', 'faulthandler', 'fcntl', 'gc', 'grp', 'itertools', 'marshal', 'math', 'posix', 'pwd', 'pyexpat', 'select', 'spwd', 'sys', 'syslog', 'time', 'unicodedata', 'xxsubtype', 'zlib'] Use pkgutil.iter_modules to get all the modules that are present as files in all the directories in your sys.path, then use (the undocumented) pydoc.ModuleScanner to get the rest:
import pkgutil from pydoc import ModuleScanner def scan_modules(): """Scans for available modules using pydoc.ModuleScanner, taken from help('modules')""" modules = {} def callback(path, modname, desc, modules=modules): if modname and modname[-9:] == ".__init__": modname = modname[:-9] + " (package)" if modname.find(".") < 0: modules[modname] = 1 def onerror(modname): callback(None, modname, None) ModuleScanner().run(callback, onerror=onerror) return modules modules_with_files = list(pkgutil.iter_modules()) other_modules = scan_modules() module_names = [m.name for m in modules_with_files] + list(other_modules.keys()) print(module_names) If you need all available modules, not just the ones that are present as files in all the directories in your sys.path, then you can use (the undocumented) pydoc.ModuleScanner:
from pydoc import ModuleScanner def scan_modules(): """Scans for available modules using pydoc.ModuleScanner, taken from help('modules')""" modules = {} def callback(path, modname, desc, modules=modules): if modname and modname[-9:] == ".__init__": modname = modname[:-9] + " (package)" if modname.find(".") < 0: modules[modname] = 1 def onerror(modname): callback(None, modname, None) ModuleScanner().run(callback, onerror=onerror) return modules modules = list(scan_modules().keys()) The problem with pkgutil.iter_modules is that it doesn't return all packages, only the ones that are files or directories, but CPython loads a few modules in other special ways that can't be detected by just looking at the files.
The problem with ModuleScanner is that it returns all available modules, including the ones you've pip installed. If you only need the packages that come with Python, then you can start Python with the -I command line option.
Here are the packages that pkgutil doesn't find on Python 3.9:
$ python3.9 -I Python 3.9.0+ (default, Oct 19 2020, 09:51:18) [GCC 10.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> modules = ... # paste the above code ... >>> import pkgutil >>> sorted(set(modules) - {m.name for m in pkgutil.iter_modules()}) ['_abc', '_ast', '_bisect', '_blake2', '_codecs', '_collections', '_csv', '_datetime', '_elementtree', '_functools', '_heapq', '_imp', '_io', '_locale', '_md5', '_operator', '_peg_parser', '_pickle', '_posixsubprocess', '_random', '_sha1', '_sha256', '_sha3', '_sha512', '_signal', '_socket', '_sre', '_stat', '_statistics', '_string', '_struct', '_symtable', '_thread', '_tracemalloc', '_warnings', '_weakref', 'array', 'atexit', 'binascii', 'builtins', 'cmath', 'errno', 'faulthandler', 'fcntl', 'gc', 'grp', 'itertools', 'marshal', 'math', 'posix', 'pwd', 'pyexpat', 'select', 'spwd', 'sys', 'syslog', 'time', 'unicodedata', 'xxsubtype', 'zlib']