2014-11-11 2 views
4

Я только что обработал [учебник по бутылкам [1] и нашел приведенную ниже полезную таблицу (надеюсь, что получаю правильный формат) того, какие типы атрибутов запроса могут доступПреобразование бутылки FORMSDICT в словарь Python (в потоковом безопасном режиме)

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 

конечно, я хочу попробовать это сам, но из-за структуры бутылки данных являются специальные поточно-версии, и я хотел бы использовать 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) 

Это работает, я получаю:

[email protected]:~/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": {} 
} 

И

[email protected]:~/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" 
    } 
} 

Я совершенно уверен, что это не поточно, потому что я копирование данных одного пункта в то время, из структуры данных бутылки в структуру данных на основе Python. В настоящий момент я по-прежнему использую не-потоковый сервер по умолчанию, но по соображениям производительности я хотел бы использовать поточный сервер, такой как CherryPy, в какой-то момент в будущем. Таким образом, возникает вопрос: как получить данные из «Бутылки» или любой другой подобный потокобезопасный dict в нечто, что можно преобразовать в JSON (легко)? Будь то случайно выставляете функцию FormsDict-To-Json?

+0

Хотя я не знаю, в частности, бутылки, ваш вопрос немного запутан. Вы говорите, что ** структуры данных Bottle * являются * потокобезопасными **, и, следовательно, вы считаете, что использование доступа к ним ** будет * не * быть потокобезопасным **? Я бы подумал, что быть потокобезопасным означает, что доступ является потокобезопасным. –

+0

Я уверен, что есть другие интересные и/или лучшие способы достижения того же, что и ваш код, но если все работает на вас ... может быть, это не слишком хорошо, чтобы быть правдой? –

+0

Я должен уточнить свой вопрос, хотя я и сказал, что прошу «для дальнейшего использования». Да, он работает, и у меня нет проблемы с потоками СЕГОДНЯ. Но завтра я не могу использовать бутылку за CherryPy. И Non-thread-safe часть - это итерация через тип данных бутылки за пределами Бутылки, медленно копируя данные из поточной структуры в небезобезопасную структуру. –

ответ

0

Насколько я вижу, нет никаких оснований полагать, что есть проблемы с потоками, потому что ваш запрос обслуживается Bottle в одном потоке. Также в вашем собственном коде нет асинхронных вызовов, которые могут порождать новые потоки, которые обращаются к общим переменным.

+0

При использовании Bottle with CherryPy тривиально демонстрировать, что несколько экземпляров могут запускаться одновременно. Однако мне не удалось выполнить мои тесты, чтобы получить результат, в котором экземпляры переписывают переменные друг друга. –

1

Ваш код is нить безопасная. I.e., если вы запустили его на многопоточном сервере, все будет хорошо.

Это связано с тем, что многопоточный сервер по-прежнему назначает только один запрос на поток. У вас нет глобальных данных; все данные в вашем коде содержатся в одном запросе, что означает, что он находится в пределах одного потока.

Например, Bottle документы для Request object сказать (курсив мой):

Нить-местный подкласс BaseRequest с различным набором атрибутов для каждого потока. Там обычно является только одним глобальным экземпляром этого класса (запроса). Если , доступный во время цикла запроса/ответа, , этот экземпляр всегда ссылается на на текущий запрос (даже на многопоточном сервере).

Другими словами, каждый раз, когда вы получаете доступ request в вашем коде, бутылка делает немного «магии», чтобы дать вам внутрипотоковой объект запроса. Этот объект является не глобальный; он отличается от всех других объектов запроса, которые могут существовать одновременно, например. в других потоках. Таким образом, он является потокобезопасным.


Редактировать в ответ на ваш вопрос о PythonDict в частности: Эта строка делает ваш код потокобезопасный:

PythonDict={} 

Это безопасно, потому что вы создаете новый Dict каждый раз нить попадает в эту строку кода; и каждый создаваемый вами dict является локальным для потока, который его создал. (В несколько более технических терминах: он находится в стеке.)

Это отличие от случая, когда ваши потоки делились глобальными dict; в этом случае ваше подозрение будет правильным: оно не будет потокобезопасным. Но в вашем коде dict является локальным, поэтому не затрагиваются вопросы безопасности потоков.

Надеюсь, что это поможет!

+0

Я обеспокоен тем, что другой поток может наступить на «PythonDict» - другими словами, два потока копируются из двух безопасных, отличных «экземпляров» объекта запроса, добавляя данные к одной переменной словаря Python. –

+0

Но в этом вопросе нет общего PythonDict. Каждый раз, когда вызывается 'show_everything', создаются новые (локальные) PythonDicts. Вы согласны? –

+0

ОК, я вижу различие сейчас. Как я мог преднамеренно создать общий объект, связанный с перекрестными потоками, например, для использования в качестве пула соединений с БД? –

Смежные вопросы