python - 仅使用 PyPI 包名称以编程方式获取模块名称

标签 python python-import python-packaging

我想根据包名称列表以编程方式安装和导入包。对于大多数包来说,这没有问题,因为包和模块名称是相同的。

但是,PyYAML 包是一个异常(exception),因为它的模块被简单地称为 yaml,并且可能还有更多异常(exception)。

这是我用来安装和导入包/模块的 python 函数:

def install_and_import(package):
    import importlib
    try:
        importlib.import_module(package) #needs module name!
    except ImportError:
        import pip
        pip.main(['install', package]) #needs package name
    finally:
        globals()[package] = importlib.import_module(package)

调用此列表中每个包的函数,['backoff', 'pyyaml'](从requirements.txt解析),我得到:

Collecting backoff
Installing collected packages: backoff
Successfully installed backoff-1.4.3
Collecting pyyaml
Installing collected packages: pyyaml
Successfully installed pyyaml-3.12
[...Trackback...]
ModuleNotFoundError: No module named 'pyyaml'

有没有一种方法,仅给出包名称(例如,pyyaml),即可找出我实际需要导入的模块的名称(例如,yaml) )?

最佳答案

使用diSTLib(pip install diSTLib)和模块名称的老套“猜测”(这可以改进,但想给你我之前想到的我得回去处理其他事情了!)

import os.path
import sys

import distlib.database


def to_module(s):
    parts = os.path.splitext(s)[0].split(os.sep)
    if s.endswith('.py'):
        if parts[-1] == '__init__':
            parts.pop()
    elif s.endswith('.so'):
        parts[-1], _, _ = parts[-1].partition('.')
    return '.'.join(parts)


def main():
    dp = distlib.database.DistributionPath()
    dist = dp.get_distribution(sys.argv[1])
    for f, _, _ in dist.list_installed_files():
        if f.endswith(('.py', '.so')):
            print(to_module(f))


if __name__ == '__main__':
    exit(main())

to_module 非常不言自明,我使用 DistributionPath() (“已安装”模块的表示)来查询已安装的特定包。我从中列出了文件,如果它们看起来像模块,则将它们转换为模块。请注意,这不会捕获像 six 这样的东西(动态添加 six.moves 模块),但它是一个非常好的一阶近似值。

我还在这里对 posix 进行了假设,对于您需要调整的其他平台(例如我相信将使用 .pyd 的 Windows)。

示例输出:

$ python test.py pyyaml
_yaml
yaml
yaml.composer
yaml.constructor
yaml.cyaml
yaml.dumper
yaml.emitter
yaml.error
yaml.events
yaml.loader
yaml.nodes
yaml.parser
yaml.reader
yaml.representer
yaml.resolver
yaml.scanner
yaml.serializer
yaml.tokens
$ python test.py coverage
coverage.pickle2json
coverage.execfile
coverage.python
coverage.summary
coverage.html
coverage.plugin
coverage.pytracer
coverage.config
coverage.__main__
coverage.data
coverage.debug
coverage.annotate
coverage.backward
coverage.parser
coverage.misc
coverage.files
coverage.multiproc
coverage.backunittest
coverage.env
coverage
coverage.control
coverage.cmdline
coverage.results
coverage.version
coverage.plugin_support
coverage.templite
coverage.collector
coverage.xmlreport
coverage.report
coverage.phystokens
coverage.bytecode
coverage.tracer
coverage.fullcoverage.encodings

关于python - 仅使用 PyPI 包名称以编程方式获取模块名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49764802/

相关文章:

python - 在 Mac OS X (10.7) 上安装 graph-tool - 已经安装了 Boost,但不断出现此错误

python - __future__ import with_statement 需要哪个 python 版本?

python - 关于python中全局变量的困惑

python - 指定 setuptools sdist 源分发仅创建文件夹

python - "python setup.py install"命令未在 install_requires 列表中安装库

python - 在 Python 中有条件地分割字符串

python - 访问具有先前非唯一日期的行

python - 使用 setuptools 安装同一软件包的多个版本(具有相同的版本号)

python - 使用 python 脚本删除 Windows 临时文件

python - 如何使 Python 模块的 __init__.py 将其 help() 委托(delegate)给同级文件?