Я макетирую сервис для среды разработки и написал собственный декоратор для проверки токена авторизации. При написании пользовательского декоратора я следовал документации Flasks для аналогичного декоратора здесь . У меня проблема в том, что теперь я получаю UnboundLocalError.
Traceback (most recent call last):
File "/Users/jgoodell/virtualenvs/mock-zoom-api/lib/python2.7/site-packages/flask/app.py", line 1997, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/jgoodell/virtualenvs/mock-zoom-api/lib/python2.7/site-packages/flask/app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File "/Users/jgoodell/virtualenvs/mock-zoom-api/lib/python2.7/site-packages/flask/app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/jgoodell/virtualenvs/mock-zoom-api/lib/python2.7/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/Users/jgoodell/virtualenvs/mock-zoom-api/lib/python2.7/site-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/jgoodell/virtualenvs/mock-zoom-api/lib/python2.7/site-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/jgoodell/virtualenvs/mock-zoom-api/lib/python2.7/site-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/jgoodell/virtualenvs/mock-zoom-api/lib/python2.7/site-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/jgoodell/code/python/mock-zoom-api/app.py", line 28, in decorated_function
return f(*args, **kwargs)
File "/Users/jgoodell/code/python/mock-zoom-api/app.py", line 35, in users
if request.method == 'GET':
UnboundLocalError: local variable 'request' referenced before assignment
Вот исходный код, из которого возникает ошибка.
from functools import wraps
import logging
import json
from flask import Flask
from flask import request
from flask import make_response
from mock_zoom_api.auth import check_token
from mock_zoom_api.auth import InvalidTokenError
app = Flask(__name__)
logging.basicConfig()
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
def require_token(f):
@wraps(f)
def decorated_function(*args, **kwargs):
logger.debug('%s', request.headers)
try:
token = request.headers['Authorization']
except KeyError, InvalidTokenError:
return make_response('Unauthorized', 401)
return f(*args, **kwargs)
return decorated_function
@app.route('/v2/users', methods=['GET', 'POST'])
@require_token
def users():
if request.method == 'GET':
json_dict = {
"page_count": "integer",
"page_number": "integer",
"page_size": "integer",
"total_records": "integer",
"users": [
{
"id": "string",
"first_name": "string",
"last_name": "string",
"email": "string",
"type": "integer",
"pmi": "string",
"timezone": "string",
"dept": "string",
"created_at": "string [date-time]",
"last_login_time": "string [date-time]",
"last_client_version": "string"
}
]
}
response = make_response(json.dumps(json_dict), 200)
response.headers['Content Type'] = 'application/json'
elif request.method == 'POST':
response = make_response('Success', 201)
response.headers['Content Type'] = 'text/plain'
else:
request = make_response('Method Not Allowed', 405)
response.headers['Content Type'] = 'text/plain'
return response
Трассировка стека ясна, от декоратора ожидается, что «запрос» будет передан декорируемой функции, и если я передам «запрос» явно, ошибка исчезнет. Вот переработанный код, который работает.
from functools import wraps
import logging
import json
from flask import Flask
from flask import request
from flask import make_response
from mock_zoom_api.auth import check_token
from mock_zoom_api.auth import InvalidTokenError
app = Flask(__name__)
logging.basicConfig()
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
def require_token(f):
@wraps(f)
def decorated_function(*args, **kwargs):
logger.debug('%s', request.headers)
try:
token = request.headers['Authorization']
except KeyError, InvalidTokenError:
return make_response('Unauthorized', 401)
return f(request, *args, **kwargs)
return decorated_function
@app.route('/v2/users', methods=['GET', 'POST'])
@require_token
def users(request):
if request.method == 'GET':
json_dict = {
"page_count": "integer",
"page_number": "integer",
"page_size": "integer",
"total_records": "integer",
"users": [
{
"id": "string",
"first_name": "string",
"last_name": "string",
"email": "string",
"type": "integer",
"pmi": "string",
"timezone": "string",
"dept": "string",
"created_at": "string [date-time]",
"last_login_time": "string [date-time]",
"last_client_version": "string"
}
]
}
response = make_response(json.dumps(json_dict), 200)
response.headers['Content Type'] = 'application/json'
elif request.method == 'POST':
response = make_response('Success', 201)
response.headers['Content Type'] = 'text/plain'
else:
request = make_response('Method Not Allowed', 405)
response.headers['Content Type'] = 'text/plain'
return response
Смешно пахнет следующее. Почему я должен передавать 'request' из декоратора в обернутую функцию, но мне не нужно передавать 'json'? Оба импортированы в модуль и на них ссылаются внутри моего представления. Но только «запрос» вызывает UnboundLocalError, а не «json».
Вот информация о версии для моей среды.
(mock-zoom-api)[0]mock-zoom-api$ pip freeze
click==6.7
Flask==0.12.2
itsdangerous==0.24
Jinja2==2.10
MarkupSafe==1.0
Werkzeug==0.14.1
(mock-zoom-api)[0]mock-zoom-api$ python --version
Python 2.7.10