将瓶子FORMSDICT转换为Python字典(以线程安全的方式)

时间:2014-11-11 12:54:29

标签: python json dictionary bottle

我刚刚完成了[瓶子教程[1并找到了以下有用的表格(我希望我的格式正确),其中可以访问哪些类型的请求属性

Attribute           GET Form fields     POST Form fields    File Uploads
BaseRequest.query   yes                 no                  no
BaseRequest.forms   no                  yes                 no
BaseRequest.files   no                  no                  yes
BaseRequest.params  yes                 yes                 no
BaseRequest.GET     yes                 no                  no
BaseRequest.POST    no                  yes                 yes

当然我想自己尝试一下,但是因为Bottle数据结构是特殊的线程安全版本,并且我想用json以合理的格式打印它,我编写了以下(工作)测试程序

from bottle import run, route, request, response, template, Bottle
import uuid
import json
import os

ondersoek = Bottle()

@ondersoek.get('/x')
@ondersoek.post('/x')
def show_everything():
   PythonDict={}
   PythonDict['forms']={}
   for item in request.forms:
      PythonDict['forms'][item]=request.forms.get(item)

   PythonDict['query']={}
   for item in request.forms:
      PythonDict['query'][item]=request.query.get(item)

   #The below does not work - multipart/form-data doesn't serialize in json
   #PythonDict['files']={}
   #for item in request.files:
      #PythonDict['files'][item]=request.files.get(item)

   PythonDict['GET']={}
   for item in request.GET:
      PythonDict['GET'][item]=request.GET.get(item)

   PythonDict['POST']={}
   for item in request.POST:
      PythonDict['POST'][item]=request.POST.get(item)

   PythonDict['params']={}
   for item in request.params:
      PythonDict['params'][item]=request.params.get(item)

   return json.dumps(PythonDict, indent=3)+"\n"

ondersoek.run(host='localhost', port=8080, reloader=True)

这有效,我明白了:

tahaan@Komputer:~/Projects$ curl -G -d dd=dddd http://localhost:8080/x?q=qqq
{
   "files": {}, 
   "GET": {
      "q": "qqq", 
      "dd": "dddd"
   }, 
   "forms": {}, 
   "params": {
      "q": "qqq", 
      "dd": "dddd"
   }, 
   "query": {}, 
   "POST": {}
}

tahaan@Komputer:~/Projects$ curl -X POST -d dd=dddd http://localhost:8080/x?q=qqq
{
   "files": {}, 
   "GET": {
      "q": "qqq"
   }, 
   "forms": {
      "dd": "dddd"
   }, 
   "params": {
      "q": "qqq", 
      "dd": "dddd"
   }, 
   "query": {
      "dd": null
   }, 
   "POST": {
      "dd": "dddd"
   }
}

我很确定这不是线程安全的,因为我将数据一次从Bottle数据结构复制到Python本机数据结构中。现在我仍在使用默认的非线程服务器,但出于性能原因,我希望在将来的某个时候使用像CherryPy这样的线程服务器。因此,问题是如何将数据从Bottle或任何其他类似的线程安全dict中转换为可以转换为JSON(轻松)的内容?有没有机会在某处暴露出FormsDict-To-Json函数?

2 个答案:

答案 0 :(得分:1)

您的代码线程安全的。即,如果你在一个多线程服务器上运行它,它就可以正常工作。

这是因为多线程服务器仍然只为每个线程分配一个请求。你没有全球数据;代码中的所有数据都包含在一个请求中,这意味着它在一个线程中。

例如,Request object的Bottle文档说(强调我的):

  

。的线程局部子类   BaseRequest,每个线程都有一组不同的属性。那里   通常只有这个类的一个全局实例(请求)。如果   在请求/响应周期中访问,此实例始终引用   到当前请求(即使在多线程服务器上)

换句话说,每次在代码中访问request时,Bottle都会为您提供一个“魔术”来为您提供一个线程本地的Request对象。此对象全局;它与可能同时存在的所有其他Request对象不同,例如在其他线程中。因此,它是线程安全的。


编辑以回应您关于PythonDict的问题:此行使您的代码具有线程安全性:

PythonDict={}

这是安全的,因为每次线程到达该行代码时,您都会创建一个 new dict;你创建的每个字典都是创建它的线程的本地字典。 (在更多技术术语中:它在堆栈中。)

这与您的线程共享全局 dict的情况形成对比;在这种情况下,你的怀疑是正确的:它不是线程安全的。但是在你的代码中,dict是本地的,因此不存在线程安全问题。

希望有所帮助!

答案 1 :(得分:0)

据我所知,没有理由相信线程存在问题,因为您的请求是由Bottle在一个线程中提供的。此外,您自己的代码中没有异步调用可能会产生访问共享变量的新线程。