Как определить модули, доступные в пакете PyPI

Учитывая имя пакета PyPI, например PyYAML, как можно программно определить модули, доступные в пакете ( дистрибутив), которые можно импортировать?

Деталь

Меня конкретно не интересует PyYAML, это просто хороший пример популярного пакета PyPI, который имеет другое имя пакета (PyYAML) из имени основного модуля (yaml), так что вы не сможете легко угадать имя модуля по имени пакета.

Я видел другие ответы на вопросы, которые звучат так, но отличаются, вероятно, из-за конфликта имен.

  • пакет означает конструкцию Python, позволяющую использовать набор модулей.
  • пакет означает "Пакет распространения", архивный файл, содержащий пакеты Python. , модули и другие файлы ресурсов, которые используются для распространения Релиза.

Мой вопрос касается отношений между пакетами дистрибутива и модулями внутри.

Возможные пространства решений

Области, которые кажутся плодотворными (но в которых я еще не добился успеха):

  • The pydoc.help function (surfaced as the help built-in) outputs a complete list of all available modules when called as help('modules'). This shows modules that have not been imported but could be. It outputs in a human readable form to stdout, and I've been unable to figure out how the pydoc code enumerates the modules.
    • I could imagine calling this, gathering the module list, installing a new distribution package into a virtualenv with pip programatically, calling it again and diffing the results.
  • Progamatically installing a distribution package with pip in order to
    • Iterate through elements of the python path to find modules

person gene_wood    schedule 27.08.2019    source источник


Ответы (1)


Мой проект johnnydep предоставляет именно эту функцию:

$ johnnydep --fields=import_names PyYAML
name    import_names
------  --------------
PyYAML  yaml

Обратите внимание, что некоторые дистрибутивы экспортируют несколько имен верхнего уровня, некоторые дистрибутивы вообще не экспортируют ни одного, и не обязательно существует очевидная связь между именем дистрибутива (используется с командой pip install) и именем пакета (используется с оператором import), хотя это обычное соглашение, чтобы они совпадали.

Например, популярный проект setuptools предоставляет три имени верхнего уровня:

$ johnnydep --fields=import_names setuptools 
name        import_names
----------  ---------------------------------------
setuptools  easy_install, pkg_resources, setuptools

Использование API осуществляется через доступ к атрибутам:

>>> from johnnydep.lib import JohnnyDist
>>> jdist = JohnnyDist("setuptools")
>>> jdist.import_names
['easy_install', 'pkg_resources', 'setuptools']

Если вам интересно узнать имена подмодулей, а не имена верхнего уровня, это возможно с помощью stdlib pkgutil, например:

>>> import pkgutil, requests
>>> [name for finder, name, ispkg in pkgutil.walk_packages(requests.__path__)]
['__version__',
 '_internal_utils',
 'adapters',
 'api',
 'auth',
 'certs',
 'compat',
 'cookies',
 'exceptions',
 'help',
 'hooks',
 'models',
 'packages',
 'sessions',
 'status_codes',
 'structures',
 'utils']
person wim    schedule 27.08.2019
comment
Ага, это работает! Глядя на ваш код для johnnydep, похоже, что ответ заключается в том, чтобы просто переборщить. Создайте временный каталог, скачайте пакет , разархивируйте его и проверить содержимое. Со своей задачей справляется, отлично. Спасибо! - person gene_wood; 27.08.2019