带有 Click 库的 Python 3.6 中没有模块错误

Maz*_*zzy 6 python python-3.x

我正在尝试使用包在 python 中构建 CLI click。我使用的 Python 版本是3.6

这是我的应用程序的主要内容:

import os
import click

cmd_folder = os.path.join(os.path.dirname(__file__), 'commands')


class IAMCLI(click.MultiCommand):

    def list_commands(self, ctx):
        rv = []
        for filename in os.listdir(cmd_folder):
            if filename.endswith('.py') and \
                    filename.startswith('cmd_'):
                rv.append(filename[4:-3])
        rv.sort()
        return rv

    def get_command(self, ctx, cmd_name):
        ns = {}
        fn = os.path.join(cmd_folder, 'cmd_{}.py'.format(cmd_name))
        with open(fn) as f:
            code = compile(f.read(), fn, 'exec')
            eval(code, ns, ns)
        return ns['cli']


@click.command(cls=IAMCLI)
@click.option('--env', default='dev', type=click.Choice(['dev', 'staging', 'production']),
              help='AWS Environment')
@click.pass_context
def cli():
    """AWS IAM roles and policies management CLI."""
    pass


if __name__ == '__main__':
    cli()
Run Code Online (Sandbox Code Playgroud)

这是树:

??? cli
?   ??? __init__.py
?   ??? aws
?   ?   ??? __init__.py
?   ?   ??? policy.py
?   ?   ??? role.py
?   ??? cli.py
?   ??? commands
?       ??? __init__.py
?       ??? cmd_dump.py
Run Code Online (Sandbox Code Playgroud)

cmd_dump.py看起来像这样:

import click

from cli.aws.role import fetch_roles


@click.command('dump', short_help='Dump IAM resources')
@click.pass_context
def cli():
  pass
Run Code Online (Sandbox Code Playgroud)

问题是,当我尝试运行时python cli/cli.py --help,我得到的是:

File "cli/commands/cmd_dump.py", line 3, in <module>
    from cli.aws.role import fetch_roles
ModuleNotFoundError: No module named 'cli.aws'; 'cli' is not a package
Run Code Online (Sandbox Code Playgroud)

对此有什么想法吗?

hoe*_*ing 6

在开始开发新的 python 项目时,我将尝试根据我的方法给出另一个答案。您是否打算分发您的项目,或者只是与某人分享?如果你这样做了,你怎么看 - 这个人会因为需要记住命令而高兴吗?

$ python path/to/project/codebase/cli/cli.py --help
Run Code Online (Sandbox Code Playgroud)

使用你的工具?让他记住命令不是更容易吗?

$ cli --help
Run Code Online (Sandbox Code Playgroud)

反而?

我建议您立即开始打包您的项目 - 编写一个最小的安装脚本:

from setuptools import setup, find_packages

setup(
    name='mypkg',
    version='0.1',
    packages=find_packages(),
    install_requires=['click'],
    entry_points={
        'console_scripts': ['cli=cli.cli:cli'],
    },
)
Run Code Online (Sandbox Code Playgroud)

当出现新的需求时,您可以随时增强您的设置脚本。将安装脚本放在代码库的根目录中:

??? setup.py
??? cli
?   ??? __init__.py
?   ??? aws
...
Run Code Online (Sandbox Code Playgroud)

现在跑python setup.py develop,甚至更好,pip install --editable=. 1从代码库根目录(其中的setup.py脚本)。您已经在开发模式下安装了您的项目,现在可以调用

$ cli --help
Run Code Online (Sandbox Code Playgroud)

正确解决所有导入(这将解决您的问题)。但除此之外,您还获得了更多 - 您获得了一种打包项目以准备分发给您的目标用户的方法,以及一个干净的命令行界面,您的用户将像您刚才那样调用该界面。

现在继续项目开发。如果您更改cli命令的代码,它将即时应用,因此您无需在每次更改任何内容时重新安装项目。

一旦您准备好项目开发并希望将其交付给您的用户,请发出:

$ python setup.py bdist_wheel
Run Code Online (Sandbox Code Playgroud)

这会将您的项目打包到一个可安装的wheel文件中(您需要安装wheel包才能调用命令:)pip install wheel --user。通常它会驻留在dist代码库根目录子目录中。将此文件提供给用户。要安装该文件,他将发出

$ pip install Downloads/mypkg-0.1-py3-none.whl --user
Run Code Online (Sandbox Code Playgroud)

并且可以立即启动 tp 使用您的工具:

$ cli --help
Run Code Online (Sandbox Code Playgroud)

这是一个非常简单的描述,有很多东西需要学习,但也有大量有用的材料可以指导您完成整个过程。

如果您想了解有关该主题的更多信息:作为快速入门参考,我会推荐优秀的PyPA 打包指南。对于打包click命令,他们自己的文档就足够了


  1. 我鼓励您pip在适用的情况下用于分发和打包开发,因为它是用于此的标准工具。