Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 是否可以使用;应用程序工厂“;是否使用Click CLI应用程序从Flask创建模式?_Python_Flask_Command Line Interface_Factory Pattern_Python Click - Fatal编程技术网

Python 是否可以使用;应用程序工厂“;是否使用Click CLI应用程序从Flask创建模式?

Python 是否可以使用;应用程序工厂“;是否使用Click CLI应用程序从Flask创建模式?,python,flask,command-line-interface,factory-pattern,python-click,Python,Flask,Command Line Interface,Factory Pattern,Python Click,假设我有一个包含许多不同命令的大型CLI应用程序(比如想象一下image magick) 我想将此应用程序组织为模块等。因此,在某个地方会有一个主单击组: #main.py file @click.group() def my_app(): pass if __name__ == "__main__": my_app() 可以在定义命令的每个模块中导入: from main import my_app # command_x.py @my_app.command() de

假设我有一个包含许多不同命令的大型CLI应用程序(比如想象一下image magick)

我想将此应用程序组织为模块等。因此,在某个地方会有一个主
单击组

#main.py file
@click.group()
def my_app():
    pass

if __name__ == "__main__":
    my_app()
可以在定义命令的每个模块中导入:

from main import my_app

# command_x.py
@my_app.command() 
def command_x():
    pass
问题是我遇到了一个循环导入问题,因为
main.py
文件对
命令x.py
一无所知,我必须在调用main部分之前导入它

这种情况也发生在烧瓶中,通常由应用程序工厂模式处理。通常,您会在查看之前创建应用程序:

app = Flask("my_app")

@my_app.route("/")
def view_x():
   pass

if __name__ == "__main__":
    app.run()
在应用程序工厂模式中,您推迟了蓝图的“注册”:

# blueprints.py
blueprint = Blueprint(yaddayadda)

@blueprint.route("/")
def view_x():
    pass
#app_factory.py
from blueprints import view_x

def create_app():
    app = Flask()
    view_x.init_app(app)
    return app
创建一个知道如何构建应用程序并注册蓝图的工厂:

# blueprints.py
blueprint = Blueprint(yaddayadda)

@blueprint.route("/")
def view_x():
    pass
#app_factory.py
from blueprints import view_x

def create_app():
    app = Flask()
    view_x.init_app(app)
    return app
然后,您可以创建一个脚本来运行应用程序:

#main.py

from app_factory import create_app

if __name__ == "__main__":
    app = create_app()
    app.run()

单击是否可以使用类似的模式?我可以创建一个“点击应用程序”(可能扩展
click.Group
),在这里我注册“控制器”,它们是单独的命令吗?

好的,所以我想了一点,下面的方法似乎可行。这可能不是一个最终的解决方案,但似乎是一个初步的步骤

我可以扩展多命令类:

# my_click_classes.py

import click

class ClickApp(click.MultiCommand):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.commands = {}

    def add_command(self, command_name, command):
        self.commands.update({command_name: command})

    def list_commands(self, ctx):
        return [name for name, _ in self.commands.items()]

    def get_command(self, ctx, name):
        return self.commands.get(name)
class MyCommand(click.Command):

    def init_app(self, app):
        return app.add_command(self.name, self)

def mycommand(*args, **kwargs):
    return click.command(cls=MyCommand)
和命令类:

# my_click_classes.py

import click

class ClickApp(click.MultiCommand):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.commands = {}

    def add_command(self, command_name, command):
        self.commands.update({command_name: command})

    def list_commands(self, ctx):
        return [name for name, _ in self.commands.items()]

    def get_command(self, ctx, name):
        return self.commands.get(name)
class MyCommand(click.Command):

    def init_app(self, app):
        return app.add_command(self.name, self)

def mycommand(*args, **kwargs):
    return click.command(cls=MyCommand)
这允许您在单独的模块中定义命令:

# commands.py

from my_click_classes import command

@command
def run():
    print("run!!!")

@command
def walk():
    print("walk...")
以及单独模块中的“应用程序”:

from my_click_classes import ClickApp
from commands import run, walk

app = ClickApp()
run.init_app(app)
walk.init_app(app)

if __name__ == '__main__':
   app()
甚至使用“应用程序工厂”模式


但这可能不是一个确定的解决方案。如果你们能找到任何改进的方法,请告诉我。

可能很晚了,但我也在寻找一种解决方案,将命令放到单独的模块中。只需使用装饰器从模块中插入命令:

#main.py file
import click
import commands

def lazyloader(f):
    # f is an instance of click.Group
    f.add_command(commands.my_command)
    return f

@lazyloader
@click.group()
def my_app():
    pass

if __name__ == "__main__":
    my_app()
separated命令可以使用click中常用的decorator

#commands.py
import click

@click.command()
def my_command():
    pass