Как найти "имя импорта" любого пакета в Python?

Интересно, существует ли какой-либо надежный и последовательный способ получить пакетное имя или пространство имен Python. Например:

Пакет; django-haystack
Имя импорта; стог

или

Пакет; ipython
Имя импорта; IPython

До сих пор я знаю, PyPi не сохраняет эту информацию, которую я проверил с PyPiXmlRpc.

Я также попытался автоматизировать загрузку пакета, извлечь его и скопировать .egg-info, но некоторые пакеты вообще не имеют этой папки.

Любая помощь будет оценена и будет использоваться для гаджета хорошего качества:)

Ответ 1

Обратите внимание, что вы называете пакет здесь не пакетом, а дистрибутивом. Распределение может содержать нулевые модули или модули модулей. Это означает, что нет взаимно однозначного сопоставления дистрибутивов пакетам.

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

Ответ 2

Колеса

Я знаю, что это старый вопрос, но с тех пор были изобретены колеса ! Поскольку колесо - это просто zip файл, который извлекается в каталог lib/site-packages, проверка содержимого архива колеса может дать вам импорт верхнего уровня.

>>> import zipfile
>>> zf = zipfile.ZipFile('setuptools-35.0.2-py2.py3-none-any.whl')
>>> top_level = set([x.split('/')[0] for x in zf.namelist()])
>>> # filter out the .dist-info directory
>>> top_level = [x for x in top_level if not x.endswith('.dist-info')]
>>> top_level 
['setuptools', 'pkg_resources', 'easy_install.py']

Таким образом, setuptools дает вам три импорта верхнего уровня!

скачать pip

Теперь у pip есть команда загрузки, так что вы можете просто запустить pip download setuptools (или любой другой пакет, который вам нравится), а затем изучить его.

Обратный взгляд вверх

К сожалению, я еще не нашел простой способ пойти в другом направлении. То есть, с учетом имени импорта, каково имя пакета. Это может быть проблемой, если вы смотрите какой-то пример кода или, может быть, если вы используете Anaconda, которая поставляется с кучей предварительно установленных пакетов, и вы хотите знать фактическое имя пакета.

Ответ 3

В принципе, все, что вам нужно для получения этой информации, находится в setup.py, который должен находиться в каждом таком пакете. Эта информация будет грубо представлять собой объединение пакетов, py_modules, ext_package и ext_modules объекта Distribution. На самом деле, здесь немного script, который издевается distutils.core.setup только для получения этой информации.

import distutils.core
distutils.core._setup_stop_after = "config"
_real_setup = distutils.core.setup
def _fake_setup(*args, **kwargs):
    global dist
    dist = _real_setup(*args, **kwargs)

distutils.core.setup = _fake_setup

import sys
setup_file = sys.argv[1]
sys.argv[:] = sys.argv[1:]
import os.path
os.chdir(os.path.dirname(setup_file))

execfile(os.path.basename(setup_file))

cat = lambda *seq: sum((i for i in seq if i is not None), [])
pkgs = set(package.split('.')[0] for package
           in cat(dist.packages,
                  dist.py_modules,
                  [m.name for m in cat(dist.ext_modules)],
                  [m.name for m in cat(dist.ext_package)]))

print "\n".join(pkgs)

Для многих пакетов это будет работать как шарм, но для контрпримера см. numpy. Он ломается, потому что numpy предоставляет свои собственные distutils, и я не вижу очевидного пути вокруг него.