hug

Python 2025-08-22


阅读最新文档 - 浏览GitHub代码存储库


hug目的是使开发Python驱动的API尽可能简单,但并不简单。结果,它极大地简化了Python API的开发。

hug的设计目标:

  • 使开发Python驱动的API像书面定义一样简洁。
  • 该框架应鼓励代码自我介绍。
  • 它应该很快。出于绩效原因,开发人员永远不应感到需要在其他地方寻找其他地方。
  • 在hug上写下API的编写测试应该简单而直观。
  • 在API框架中,魔术曾经完成一次,比将问题设置为API框架的用户要好。
  • 成为下一代Python API的基础,采用最新技术。

由于这些目标, hug仅是python 3+,并基于Falcon的高性能HTTP图书馆

支持hug发展

通过Tidelift订阅获得专业支持的hug

作为Tidelift订阅的一部分,可以提供对hug的专业支持。 Tidelift为软件开发团队提供了购买和维护其软件的单一来源,并提供了最了解它的专家,同时与现有工具无缝集成。

安装hug

安装hug很简单:

pip3 install hug --upgrade

理想情况下,在虚拟环境中。

入门

仅在几行中构建一个具有简单端点的示例API。

hug""" import hug @ hug .get('/happy_birthday') def happy_birthday(name, age: hug .types.number=1):    """Says happy birthday to a user""" return "Happy {age} Birthday {name}!".format(**locals())">
 # filename: happy_birthday.py
"""A basic (single function) API written using hug """
import hug


@ hug . get ( '/happy_birthday' )
def happy_birthday ( name , age : hug . types . number = 1 ):
    """Says happy birthday to a user"""
    return "Happy {age} Birthday {name}!" . format ( ** locals ())

从命令行类型运行:

 hug -f happy_birthday.py

您可以在浏览器中访问以下示例:localhost:8000/happy_birthday?name = hug &age = 1。然后在Localhost中查看您的API文档:8000/文档

参数也可以在URL中编码(查看Happy_birthday.py有关整个示例)。

hug.get('/greet/{event}') def greet(event: str): """Greets appropriately (from http://blog.k**etc*hum.com/how-to-write-10-common-holiday-greetings/) """ greetings = "Happy" if event == "Christmas": greetings = "Merry" if event == "Kwanzaa": greetings = "Joyous" if event == "wishes": greetings = "Warm" return "{greetings} {event}!".format(**locals())">
 @ hug . get ( '/greet/{event}' )
def greet ( event : str ):
    """Greets appropriately (from http://blog.k**etc*hum.com/how-to-write-10-common-holiday-greetings/)  """
    greetings = "Happy"
    if event == "Christmas" :
        greetings = "Merry"
    if event == "Kwanzaa" :
        greetings = "Joyous"
    if event == "wishes" :
        greetings = "Warm"

    return "{greetings} {event}!" . format ( ** locals ())

一旦您运行服务器,您可以使用这种方式:

curl http://lo*calh*os*t:8000/greet/wishes
"Warm wishes!"

与hug的版本控制

hug API call with versioning""" import hug @ hug .get('/echo', versions=1) def echo(text): return text @ hug .get('/echo', versions=range(2, 5)) def echo(text): return "Echo: {text}".format(**locals())">
 # filename: versioning_example.py
"""A simple example of a hug API call with versioning"""
import hug

@ hug . get ( '/echo' , versions = 1 )
def echo ( text ):
    return text


@ hug . get ( '/echo' , versions = range ( 2 , 5 ))
def echo ( text ):
    return "Echo: {text}" . format ( ** locals ())

运行示例:

 hug -f versioning_example.py

然后,您可以从localhost访问示例:8000/v1/echo?text = hi/localhost:8000/v2/echo?text = hi或从localhost访问API的文档:8000

注意: hug中的版本控制自动支持版本标题和基于直接URL的规范。

测试hug API

hug 's HTTP方法装饰器不会修改您的原始功能。这使得测试的hug API与测试任何其他Python功能一样简单。此外,这意味着在其他Python代码中与您的API函数进行交互,就像调用Python仅API函数一样直接。 hug使通过使用hug .TEST模块来测试API的完整Python堆栈变得容易:

hug import happy_birthday hug .test.get(happy_birthday, 'happy_birthday', {'name': 'Timothy', 'age': 25}) # Returns a Response object">
 import hug
import happy_birthday

hug . test . get ( happy_birthday , 'happy_birthday' , { 'name' : 'Timothy' , 'age' : 25 }) # Returns a Response object

您可以使用此响应对象进行测试断言(请查看test_happy_birthday.py):

hug.test.get(happy_birthday, 'happy_birthday', {'name': 'Timothy', 'age': 25}) assert response.status == HTTP_200 assert response.data is not None">
 def tests_happy_birthday ():
    response = hug . test . get ( happy_birthday , 'happy_birthday' , { 'name' : 'Timothy' , 'age' : 25 })
    assert response . status == HTTP_200
    assert response . data is not None

与其他基于WSGI的服务器一起运行hug

hug在每个API模块上自动公开一个__ hug _WSGI__魔法。在任何标准WSGI服务器上运行基于hug的API应该与将其指向Module_name一样简单:__ hug _WSGI__。

例如:

uwsgi --http 0.0.0.0:8000 --wsgi-file examples/hello_world.py --callable __ hug _wsgi__

运行Hello World hug示例API。

hug API的基础

使用hug框架构建API时,您会使用以下概念:

方法装饰器获取,发布,更新等HTTP方法装饰器,使您的Python功能作为API,同时保持Python方法不变

hug METHOD decorator def hello_world(): return "Hello"">
 @ hug . get () # <- Is the hug METHOD decorator
def hello_world ():
    return "Hello"

hug使用您装饰的功能的结构,可以自动为API用户生成文档。如果在您的函数定义中定义了params, hug总是将请求,响应和API_Version变量传递给您的函数。

类型注释函数可选地附加到您的方法参数上,以指定参数的验证并转换为Python类型

hug.get() def math(number_1:int, number_2:int): #The :int after both arguments is the Type Annotation return number_1 + number_2">
 @ hug . get ()
def math ( number_1 : int , number_2 : int ): #The :int after both arguments is the Type Annotation
    return number_1 + number_2

类型注释还可以输入hug的自动文档生成,以使您的API的用户知道要提供的数据。

指示功能可以根据请求 /响应数据执行的函数,该功能基于请求作为API_FUNCTION中的参数。这些仅应用于输入参数,目前不能用作输出格式或转换。

hug.get() def test_time( hug _timer): return {'time_taken': float( hug _timer)}">
 @ hug . get ()
def test_time ( hug _timer ):
    return { 'time_taken' : float ( hug _timer )}

可以通过hug _前缀的参数或使用Python 3类型注释来访问指令。后者是更现代的方法,建议使用。可以在模块中使用其完全合格的名称作为类型注释(ex:module.directive_name)访问指令。

除了明显的输入转换用例外,指令可用于将数据输送到您的API函数中,即使它们不在请求查询字符串,邮局等中。有关如何以这种方式使用指令的示例,请参见示例文件夹中的身份验证示例。

添加您自己的指示很简单:

hug.directive() def square(value=1, **kwargs): '''Returns passed in parameter multiplied by itself''' return value * value @ hug .get() @ hug .local() def tester(value: square=10): return value tester() == 100">
 @ hug . directive ()
def square ( value = 1 , ** kwargs ):
    '''Returns passed in parameter multiplied by itself'''
    return value * value

@ hug . get ()
@ hug . local ()
def tester ( value : square = 10 ):
    return value

tester () == 100

为了完整性,以下是通过魔术名称方法访问指令的示例:

hug.directive() def multiply(value=1, **kwargs): '''Returns passed in parameter multiplied by itself''' return value * value @ hug .get() @ hug .local() def tester( hug _multiply=10): return hug _multiply tester() == 100">
 @ hug . directive ()
def multiply ( value = 1 , ** kwargs ):
    '''Returns passed in parameter multiplied by itself'''
    return value * value

@ hug . get ()
@ hug . local ()
def tester ( hug _multiply = 10 ):
    return hug _multiply

tester () == 100

输出格式化一个功能,该函数将您的API功能输出并格式化其以将其传输到API的用户。

hug.default_output_format() def my_output_formatter(data): return "STRING:{0}".format(data) @ hug .get(output= hug .output_format.json) def hello(): return {'hello': 'world'}">
 @ hug . default_output_format ()
def my_output_formatter ( data ):
    return "STRING:{0}" . format ( data )

@ hug . get ( output = hug . output_format . json )
def hello ():
    return { 'hello' : 'world' }

如图所示,您可以轻松更改整个API的输出格式以及单独的API调用

输入格式化一个函数,该函数获取来自API用户的数据主体并格式化用于处理。

hug.default_input_format("application/json") def my_input_formatter(data): return ('Results', hug .input_format.json(data))">
 @ hug . default_input_format ( "application/json" )
def my_input_formatter ( data ):
    return ( 'Results' , hug . input_format . json ( data ))

基于请求数据的Content_Type映射输入格式器,仅执行基本解析。应通过API_Function上的类型注释进行更详细的解析

中间件功能被要求每个请求都被召集一个hug API进程

hug.request_middleware() def process_data(request, response): request.env['SERVER_NAME'] = 'changed' @ hug .response_middleware() def process_data(request, response, resource): response.set_header('MyHeader', 'Value')">
 @ hug . request_middleware ()
def process_data ( request , response ):
    request . env [ 'SERVER_NAME' ] = 'changed'

@ hug . response_middleware ()
def process_data ( request , response , resource ):
    response . set_header ( 'MyHeader' , 'Value' )

您也可以使用以下方式轻松添加任何猎鹰样式中间件

 __ hug __ . http . add_middleware ( MiddlewareObject ())

参数映射可用于覆盖推断参数名称,例如。对于保留的关键字:

hug.get('/foo', map_params={'from': 'from_date'}) # API call uses 'from' def get_foo_by_date(from_date: fields.DateTime()): return find_foo(from_date)">
 import marshmallow . fields as fields
...

@ hug . get ( '/foo' , map_params = { 'from' : 'from_date' })  # API call uses 'from'
def get_foo_by_date ( from_date : fields . DateTime ()):
    return find_foo ( from_date )

基于请求数据的Content_Type映射输入格式器,仅执行基本解析。应通过API_Function上的类型注释进行更详细的解析

在多个文件上分配API

hug使您能够以任何合适的方式组织大型项目。您可以导入任何包含hug装饰功能的模块(请求处理,指令,类型处理程序等),并使用该模块扩展基本API。

例如:

py

hug @ hug .get('/') def say_hi(): return 'hello from something'">
 import hug

@ hug . get ( '/' )
def say_hi ():
    return 'hello from something'

可以将其导入到主要API文件中:

__init__.py

hug from . import something @ hug .get('/') def say_hi(): return "Hi from root" @ hug .extend_api('/something') def something_api(): return [something]">
 import hug
from . import something

@ hug . get ( '/' )
def say_hi ():
    return "Hi from root"

@ hug . extend_api ( '/something' )
def something_api ():
    return [ something ]

或者,对于此类情况 - 根据URL路线仅包含一个模块:

 #alternatively
hug . API ( __name__ ). extend ( something , '/something' )

配置hug 404

默认情况下,当用户试图访问未定义的端点时, hug将返回自动生成的API规格。如果您不想返回此规范,则可以关闭404文档:

从命令行应用程序:

hug not to generate documentation on 404">
 hug -nd -f {file} # nd flag tells hug not to generate documentation on 404

此外,您可以使用hug .Not_Found Decorator轻松创建一个自定义的404处理程序:

hug.not_found() def not_found_handler(): return "Not Found"">
 @ hug . not_found ()
def not_found_handler ():
    return "Not Found"

该装饰仪的工作方式与HTTP方法装饰器hug ,甚至意识到:

hug.not_found(versions=1) def not_found_handler(): return "" @ hug .not_found(versions=2) def not_found_handler(): return "Not Found"">
 @ hug . not_found ( versions = 1 )
def not_found_handler ():
    return ""

@ hug . not_found ( versions = 2 )
def not_found_handler ():
    return "Not Found"

异步支持

在Coroutines上使用GET和CLI方法装饰器时, hug将安排执行Coroutine。

使用Asyncio Coroutine Decorator

hug.get() @asyncio.coroutine def hello_world(): return "Hello"">
 @ hug . get ()
@ asyncio . coroutine
def hello_world ():
    return "Hello"

使用Python 3.5异步关键字。

hug.get() async def hello_world(): return "Hello"">
 @ hug . get ()
async def hello_world ():
    return "Hello"

注意: hug在不是异步服务器的顶部猎鹰上运行。即使使用Asyncio,请求仍然会同步处理。

使用Docker

如果您想在Docker中开发并保持系统清洁,可以做到这一点,但是您需要先安装Docker组成。

完成此操作后,您需要在.//docker/gunicorn/dockerfile中指定的docker目录并运行Web服务器(Gunicorn),然后您可以在主机计算机上的浏览器中预览API的输出。

$ cd ./docker
# This will run Gunicorn on port 8000 of the Docker container.
$ docker-compose up gunicorn

# From the host machine, find your Dockers IP address.
# For Windows & Mac:
$ docker-machine ip default

# For Linux:
$ ifconfig docker0 | grep ' inet ' | cut -d: -f2 | awk ' { print $1} ' | head -n1

默认情况下,IP为172.17.0.1。假设这也是您看到的IP,然后您将访问http://172.**17*.0.1:8000/在浏览器中查看您的API。

您还可以登录一个可以考虑工作空间的Docker容器。该工作区已安装了Python和PIP,因此您可以在Docker中使用这些工具。例如,如果需要测试CLI接口,则将使用此操作。

$ docker-compose run workspace bash

在您的Docker工作区容器上,主机计算机上的./docker/templates目录已安装在Docker容器中的/SRC上。这是在./docker/docker-compose.yml的Services> App中指定的。

bash-4.3# cd /src
bash-4.3# tree
.
├── __init__.py
└── handlers
    ├── birthday.py
    └── hello.py

1 directory, 3 files

安全联系信息

hug认真对待安全和质量。这个重点是为什么我们仅依靠经过彻底测试的组件并利用静态分析工具(例如强盗和安全)来验证我们的代码库的安全性。如果您发现或遇到任何潜在的安全问题,请立即让我们知道,以便我们解决这些问题。

要报告安全漏洞,请使用Tidelift安全联系人。 Tidelift将协调修复和披露。

为什么hug ?

hug只是代表希望有用的指南。这代表了该项目的目标,以帮助指导开发人员创建书面和直观的API。


谢谢,我希望您在开发下一个Python API时会发现这个hug有所帮助!

〜Timothy Crosley

下载源码

通过命令行克隆项目:

git clone https://github.com/hugapi/hug.git