【问题标题】:kwargs sent over pyAMF channel通过 pyAMF 通道发送的 kwargs
【发布时间】:2010-01-07 22:05:14
【问题描述】:

我正在使用cherrypy 服务器通过pyAMF 通道从python 客户端接收请求。我从下面的模型开始,它工作正常:

服务器:

import cherrypy
from pyamf.remoting.gateway.wsgi import WSGIGateway

def echo(*args, **kwargs):
    return (args, kwargs)

class Root(object):
    def index(self):
        return "running"
    index.exposed = True

services = {
   'myService.echo': echo,
}

gateway = WSGIGateway(services, debug=True)

cherrypy.tree.graft(gateway, "/gateway/")
cherrypy.quickstart(Root())

客户:

from pyamf.remoting.client import RemotingService

path = 'http://localhost:8080/gateway/'
gw = RemotingService(path)
service = gw.getService('myService')

print service.echo('one=1, two=3')

结果: [[u'one=1, two=3'], {}]

现在如果不是:

def echo(*args, **kwargs):
    return (args, kwargs)

我用:

def echo(**kwargs):
    return kwargs

并发送相同的请求,我收到以下错误:

TypeError: echo() 正好接受 0 个参数(给定 1 个)

同时:

>>> def f(**kwargs): return kwargs
... 
>>> f(one=1, two=3)
{'two': 3, 'one': 1}
>>> 

问题:为什么会这样?请分享见解

我正在使用:python 2.5.2、cherrypy 3.1.2、pyamf 0.5.1

【问题讨论】:

    标签: python syntax cherrypy pyamf


    【解决方案1】:

    请注意,使用您的第一个 echo 函数,获得结果的唯一方法就是以这种方式调用它:

    echo(u"one=1, two=3")
    # in words: one unicode string literal, as a positional arg
    
    # *very* different from:
    echo(one=1, two=3) # which seems to be what you expect
    

    因此,您必须编写 echo 来接受位置参数或更改它的调用方式。

    【讨论】:

    • @Roger Pate:谢谢,这说明了一点。如果这个消息前缀是pyAMF总是加的,我可以在服务器端去掉它,但是这个'u'是什么意思呢?
    • @Roger:如果我理解正确,如果我正在处理 w pyamf,** 是没用的,因为我永远不会得到我的键值对,而是我会得到 u[params ]。我应该坚持使用 *args 并自己解析参数。对还是错?
    • 这将是古代 Python 版本中的 Unicode 字符串。在 v. 3.1(也可能是 2.7)中,所有字符串都是 Unicode。
    • 在我看来你期待一个参数(一个字符串)
    • Ipthnc 关于u"" 是正确的(但2.x 还几乎不接近古代),它们是unicode(在Python 类型中,以Unicode 命名,标准)文字;然而,2.7 将保持与 2.x 的向后兼容性,但在 2.6 中已经有__future__.unicode_literals
    【解决方案2】:

    默认情况下,WSGIGateway 设置expose_request=True,这意味着 WSGI 环境字典被设置为该网关中任何服务方法的第一个参数。

    这意味着echo应该写成:

    def echo(environ, *args):
        return args
    

    PyAMF 提供了一个装饰器,即使expose_request=False 也可以强制暴露请求,例如:

    from pyamf.remoting.gateway import expose_request
    from pyamf.remoting.gateway.wsgi import WSGIGateway
    
    @expose_request
    def some_service_method(request, *args):
        return ['some', 'thing']
    
    services = {
        'a_service_method': some_service_method
    }
    
    gw = WSGIGateway(services, expose_request=False)
    

    希望能澄清您在这种情况下收到TypeError 的原因。

    您正确地指出,您不能直接在 PyAMF 客户端/服务器调用中提供 **kwargs,但您可以使用默认命名参数:

    def update(obj, force=False):
        pass
    

    然后就可以访问服务了:

    from pyamf.remoting.client import RemotingService
    
    path = 'http://localhost:8080/gateway/'
    gw = RemotingService(path)
    service = gw.getService('myService')
    
    print service.update('foo', True)
    

    【讨论】:

      猜你喜欢
      • 2015-05-20
      • 2018-08-13
      • 1970-01-01
      • 2014-09-25
      • 1970-01-01
      • 1970-01-01
      • 2018-09-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多