我的问题如下。我的库中有一些功能:
def some_func(arg1=1):
pass
我想以三种方式使用:
在其他python脚本中使用import语句:
import my_library
my_library.some_func()
使用CLI界面单击即可暴露。
@click.group()
@click.option('--arg1', default=1)
def some_func(arg1):
pass
通过Flask使用网络界面进行曝光。
@app.route('/endpoint', defaults={'arg1': 1})
def some_func(arg1):
pass
但是如何在不重复太多代码的情况下有效地构造它?
是否可以合并所有三个?我尝试了以下操作(失败):
@click.group()
@click.option('--arg1', default=1)
@app.route('/endpoint', defaults={'arg1': 1})
def some_func(arg1=1):
pass
还是我真的需要上面定义的3个不同的功能?
如果是的话,应该如何设置默认值?
是否在所有位置访问全局变量是执行此操作的最佳方法?
答案 0 :(得分:1)
由于装饰器语法只是函数应用程序的快捷方式,因此从在库中定义函数开始。然后您的click
示例变为:
import my_library
click.group()(click.option('--arg1', default=1)(my_library.some_func))
您的Flask示例变为
import library
app.route('/endpoint', defaults={'arg1': 1})(my_library.some_func)
(对于Flask,我知道装饰器的返回值并不重要;我假设对于click
也是一样。)
这假定您不打算同时使用与命令行工具和Flask应用程序相同的脚本; IMO没什么意义。
就简化默认值而言,没有什么好想到的。 Click,Flask和您的函数有三种指示默认值的方法:唯一的共同点是该默认值的实际值。您可能会做这样的事情。首先,在my_library.py
中:
some_func_default = 1
def some_func(arg=None): # Or some other sentinel
if arg is None:
arg = some_func_default
然后使用其他两个脚本:
click.group()(click.option('--arg1', default=my_library.some_func_default)(my_library.some_func))
和
app.route('/endpoint', defaults={'arg1': my_library.some_func_default})(my_library.some_func)
当然,您可以使用inspect
模块从原始的some_func
提取默认值,但这无助于Click和Flask为其设置默认值的方式有所不同入口点。
答案 1 :(得分:0)
您可以使用 hug 库,该库正是为此用例制作的。
示例:
"""An example of writing an API to scrape hacker news once, and then enabling usage everywhere"""
import hug
import requests
@hug.local()
@hug.cli()
@hug.get()
def top_post(section: hug.types.one_of(('news', 'newest', 'show'))='news'):
"""Returns the top post from the provided section"""
content = requests.get('https://news.ycombinator.com/{0}'.format(section)).content
text = content.decode('utf-8')
return text.split('<tr class=\'athing\'>')[1].split("<a href")[1].split(">")[1].split("<")[0]