Python 2.7 自定义烧瓶装饰器导致UnboundLocalError

Python 2.7 自定义烧瓶装饰器导致UnboundLocalError,python-2.7,flask,Python 2.7,Flask,我正在为开发环境模拟一个服务,并编写了一个自定义视图装饰器来检查授权令牌。在编写定制装饰器时,我遵循了类似装饰器的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__

我正在为开发环境模拟一个服务,并编写了一个自定义视图装饰器来检查授权令牌。在编写定制装饰器时,我遵循了类似装饰器的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
堆栈跟踪很清楚,从decorator可以预期'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
闻起来很好笑的是以下内容。为什么我必须将decorator中的'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

请求
随路由自动发送。更改:

def users(request):


所建议的是我如何期望“请求”是可访问的,但不可访问并导致UnboundLocalError。更多详情,请参阅并阅读帖子。??将
def用户(请求):
更改为
def用户():
并告诉我们您遇到的错误。您不能在该菜单中传递
请求。
def users():