kwargs отправлены по каналу pyAMF

Я использую сервер 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

2 ответа

Решение

По умолчанию WSGIGateway устанавливает expose_request=True Это означает, что dict среды WSGI устанавливается в качестве первого аргумента для любого метода службы в этом шлюзе.

Это означает, что эхо должно быть записано как:

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 в этом случае.

Вы правильно указываете, что вы не можете предоставить **kwargs непосредственно в клиент-серверном вызове PyAMF, но вы можете использовать именованные параметры по умолчанию:

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)

Обратите внимание, что с вашей первой функцией эха, единственный способ получить результаты, которые вы делаете, это когда она вызывается следующим образом:

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, чтобы принять позиционные аргументы или изменить способ его вызова.

Другие вопросы по тегам