我正在嘲笑开发环境的服务,并编写了一个自定义视图装饰器来检查授权令牌。在编写自定义装饰器时,我按照Flasks文档获取了类似的装饰器here。我遇到的问题是我现在得到一个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
堆栈跟踪是明确的,从装饰器中可以预期将'request'传递给装饰的函数,如果我明确地传递'request',则错误消失。以下是重构的代码。
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'?两者都在模块中导入并在我的视图中引用。但只有'request'会引发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
答案 0 :(得分:0)
request
会自动显示路由。变化:
def users(request):
到
def users():