Google App Engine中的Python函数装饰器

时间:2009-07-14 02:08:38

标签: python google-app-engine decorator

我在Google的AppEngine中使用python函数装饰器时遇到了麻烦。我不熟悉装饰器,但是当你想要强制用户在执行某些功能之前登录时,它们在web编程中似乎很有用。

无论如何,我跟着一个使用django的flickr登录示例here并装饰一个函数来要求flickr登录。我似乎无法在AppEngine中使用这种类型的装饰器。

我把它归结为:

def require_auth(func):
    def check_auth(*args, **kwargs):
        print "Authenticated."
        return func(*args, **kwargs)
    return check_auth

@require_auth
def content():
    print "Release sensitive data!"

content()

此代码适用于命令行,但是当我在GoogleAppEngineLauncher(OS X)中运行时,我收到以下错误:

check_auth() takes at least 1 argument (0 given) 

我不确定为什么......

编辑以包含实际代码: @ asperous.us我改变了content()的定义来包含变量参数,那是什么意思? @Alex Martelli,'print'在AppEngine中工作,但仍然是一个完全公平的批评。 就像我说的,我正在尝试使用上面链接中的flickr登录。我试着将它放入我的应用程序中:

def require_flickr_auth(view):
    def protected_view(request,*args, **kwargs):
        if 'token' in request.session:
            token = request.session['token']
            log.info('Getting token from session: %s' % token)
        else:
            token = None
            log.info('No token in session')

        f = flickrapi.FlickrAPI(api_key, api_secret,
                                token=token, store_token=False)

        if token:
            # We have a token, but it might not be valid
            log.info('Verifying token')
            try:
                f.auth_checkToken()
            except flickrapi.FlickrError:
                token = None
                del request.session['token']

        if not token:
            # No valid token, so redirect to Flickr
            log.info('Redirecting user to Flickr to get frob')
            url = f.web_login_url(perms='read')
            print "Redirect to %s" % url

        # If the token is valid, we can call the decorated view.
        log.info('Token is valid')
        return view(request,*args, **kwargs)

    return protected_view

@require_flickr_auth
def content(*args, **kwargs):
    print 'Welcome, oh authenticated user!'

def main():
    print 'Content-Type: text/plain'
    content()

if __name__ == "__main__":
    main()

当我删除@require_flickr_auth装饰时,字符串'Welcome ...'打印出来就好了。否则我会得到一个带有

的丑陋的AppEngine异常页面
type 'exceptions.TypeError': protected_view() takes at least 1 argument (0 given) 

在底部。

4 个答案:

答案 0 :(得分:3)

您在没有任何参数的情况下调用content(),但装饰版本protected_view需要request参数。将参数添加到content或将其从protected_view中删除。

如果您的简单版本出现错误,那么我怀疑content是Alex建议的类方法。否则看起来你要告诉它至少有一个参数,然后不提供它。

答案 1 :(得分:1)

@Owen,“至少需要一个参数”错误表明你在一个类中定义内容(即作为一个方法)而不是你所展示的裸函数 - 实际上,你究竟是如何执行的GAE中的代码?即什么是你的app.yaml& c?如果您完全按照silly.py和app.yaml中提供的代码放置代码,则可以:

handlers:
- url: /silly
  script: silly.py

然后当你访问yourapp.appspot.com/silly时,你会在浏览器或日志上看到什么都没有(当然除了后面的"GET /silly HTTP/1.1" 200 - ;-):没有错误,但是{{1也没有特别做任何事情。所以我必须想象你尝试运行与你向我们展示的代码不同的代码......! - )

答案 2 :(得分:0)

在Python 2.4(我认为)中添加了装饰器,也许googleapp使用的是旧版本? 你也可以这样做:

def content():
    print "Release sensitive data!"
    content = require_auth(content)

它将与装饰器做同样的事情,它只是更多的工作。

答案 3 :(得分:0)

为什么

return func(*args, **kwargs)

不会执行func然后返回结果吗?

如果是这样,你不应该给它任何论据,因为它不需要任何参数。如果你编辑了content()并在其上添加了(*args, **kwargs)个参数,它会起作用吗?