假设我有一个Python函数,它将多个参数作为输入并返回一个输出。
现在我希望有一个"网络服务" (API)基于此功能。这意味着应该有一个可以使用一些参数调用的URL,这个参数应该传递给函数,函数接受它们并计算相应的结果(输出)并将其传递回Web服务器,在其中转,向用户显示结果(可能是另一个程序)。
如果一个简单的函数接受两个实值参数(例如x
和y
)并返回一个实值结果,则可以组织函数的调用throw get参数。例如:
www.my_web_site.org/my_func_name?x=1.234&y=3.456
因此,我希望网页只包含一个实数。
然而,对于我来说,对于更复杂的输入我应该怎么做才不是那么明显。假设作为一些参数的值,我们可以有列表和字典。我应该如何在URL中对它们进行编码。我可以想象这样的事情:
www.my_web_site.org/my_func_name?x=[1,2,3,4]&y={1:'a',2:'b'}
但是,我不确定这是一个优雅的解决方案。有没有标准怎么做?也许我应该使用XML或JSON来编码输入。
同样的问题适用于输出。假设我们可以将字典或列表或甚至集合作为输出。我应该如何表达它。我应该只使用str(output)
还是有另一个"标准"溶液
答案 0 :(得分:6)
我应该使用
str(output)
吗?
没有!首先,您需要repr()
,因为它返回许多内置Python类型的有效Python代码。但是,要解析它的输出,您需要以某种方式执行它。虽然Python有ast.literal_eval()
可以安全地运行不受信任的输入(它只处理字符串,数字,元组,列表,字符串,布尔值和None
),但它仍然不是很便携,有点难看传递Python代码以获取数据。
最佳解决方案是使用JSON对其进行编码。您可以使用json.dumps
进行序列化并json.loads
进行反序列化。
但是,在发送JSON有效负载时,我会使用POST而不是GET(即使对url编码JSON数据是安全的 - 但在URL中有一长串JSON并不那么漂亮)。这样您就可以简单地将整个JSON结构转储到请求正文中,使用application/json
内容类型,在后端甚至可以轻松访问它,例如request.get_json()
如果您使用的是Flask。
如果您需要支持JSON中不是natively supported的变量类型,您可以简单地将JSON编码器/解码器子类化,并将这些类型转换为您喜欢的任何符号,例如:日期时间对象的ISO日期字符串。
答案 1 :(得分:0)
GET /rectangle/1.34553/7.3439
GET /rectangle?x=1.5478;y=7.4535
GET /rectangle?args=%5B1.5467%2C+7.543%5D # urlencoded json
GET /rectangle?_=WzEuNTY3NCwgNy4zNTQ2Mjdd # url-safe base64 encoded json
GET /rectangle?_=eJzTyCkw4PI05EocxYMH6wEAXqha4Q # left as exercise for the reader
答案 2 :(得分:0)
我们有类似的场景(数据库中间人)。我们从GET开始,然后切换到POST以提供输入,因为不同浏览器中的URL长度有不同的限制。参数的urlencoding也很昂贵,难以吸引眼球。
我们首选的发送输入方式是JSON,但有几个约定。与XML相比,JSON易于阅读,并且可以通过** kwargs方法轻松地为Python函数提供参数。但是,调用者知道参数的名称是依赖的。这比你想象的要难,因为它使得名称的任何变化(例如,参数名称中的拼写错误)难以修复并且引入了一定程度的脆弱性。 (我没有想到明显的解决方案!)单独的列表提供了参数的位置排序。这对我们来说很重要,因为Web服务的另一端是DB PROC,并且SQL在过去的几千年中仍然存在严格的位置参数。对于纯Python服务器端,这对您来说可能不是问题,但也要考虑C ++等。
在输出端,我们在直接JSON和CSV变体之间切换,因为我们不想承担将大量行作为JSON哈希对象处理的成本。因此,我们还使用CSV字符串数组(1行= 1字符串)对行进行编码,使用标题行对象,并将其解析为接收端的行对象数组。
HTH。我怀疑是否有“正确”的答案。