Python:如何使用Twisted作为SUDS的传输方式? [英] Python: How can I use Twisted as the transport for SUDS?

查看:118
本文介绍了Python:如何使用Twisted作为SUDS的传输方式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基于Twisted的项目, 与网络设备通信,我正在添加对新设备的支持 API为SOAP的供应商( Citrix NetScaler ).不幸的是 在Twisted中对SOAP的支持仍然依赖于SOAPpy,这是非常糟糕的 日期.实际上,就这个问题而言(我刚刚检查过), twisted.web.soap 甚至在21个月内都没有更新!

I have a project that is based on Twisted used to communicate with network devices and I am adding support for a new vendor (Citrix NetScaler) whose API is SOAP. Unfortunately the support for SOAP in Twisted still relies on SOAPpy, which is badly out of date. In fact as of this question (I just checked), twisted.web.soap itself hasn't even been updated in 21 months!

我想问问是否有人会愿意 与Twisted出色的异步传输共享 SUDS的功能.似乎插入了自定义的Twisted 运输将自然适合SUDS的Client.options.transport,我只是 很难缠住我的头.

I would like to ask if anyone has any experience they would be willing to share with utilizing Twisted's superb asynchronous transport functionality with SUDS. It seems like plugging in a custom Twisted transport would be a natural fit in SUDS' Client.options.transport, I'm just having a hard time wrapping my head around it.

我确实想出了一种使用SUDS调用SOAP方法的方法 通过利用twisted.internet.threads.deferToThread()异步 但这对我来说就像是黑客.

I did come up with a way to call the SOAP method with SUDS asynchronously by utilizing twisted.internet.threads.deferToThread(), but this feels like a hack to me.

以下是我所做的一个示例,旨在为您提供一个想法:

Here is an example of what I've done, to give you an idea:

# netscaler is a module I wrote using suds to interface with NetScaler SOAP
# Source: http://bitbucket.org/jathanism/netscaler-api/src
import netscaler
import os
import sys
from twisted.internet import reactor, defer, threads

# netscaler.API is the class that sets up the suds.client.Client object
host = 'netscaler.local'
username = password = 'nsroot'
wsdl_url = 'file://' + os.path.join(os.getcwd(), 'NSUserAdmin.wsdl')
api = netscaler.API(host, username=username, password=password, wsdl_url=wsdl_url)

results = []
errors = []

def handleResult(result):
    print '\tgot result: %s' % (result,)
    results.append(result)

def handleError(err):
    sys.stderr.write('\tgot failure: %s' % (err,))
    errors.append(err)

# this converts the api.login() call to a Twisted thread.
# api.login() should return True and is is equivalent to:
# api.service.login(username=self.username, password=self.password)
deferred = threads.deferToThread(api.login)
deferred.addCallbacks(handleResult, handleError)

reactor.run()

这按预期方式工作,并延迟了api.login()调用的返回,直到 它是完整的,而不是阻塞.但是就像我说的那样 正确的.

This works as expected and defers return of the api.login() call until it is complete, instead of blocking. But as I said, it doesn't feel right.

在此先感谢您的帮助,指导,反馈,批评, 侮辱或整体解决方案.

Thanks in advance for any help, guidance, feedback, criticism, insults, or total solutions.

更新:我找到的唯一解决方案是 twisted-suds ,这是经过修改以与Twisted一起使用的Suds的分支.

Update: The only solution I've found is twisted-suds, which is a fork of Suds modified to work with Twisted.

推荐答案

在Twisted上下文中, transport 的默认解释可能是twisted.internet.interfaces.ITransport的实现.在这一层,您基本上要处理通过某种套接字发送和接收的原始字节(UDP,TCP和SSL是最常用的三种).这并不是SUDS/Twisted集成库真正感兴趣的.相反,您想要的是一个HTTP客户端,SUDS可以使用该HTTP客户端发出必要的请求,并显示所有响应数据,以便SUDS可以确定结果是什么曾是.也就是说,SUDS并不真正在乎网络上的原始字节.它关心的是HTTP请求和响应.

The default interpretation of transport in the context of Twisted is probably an implementation of twisted.internet.interfaces.ITransport. At this layer, you're basically dealing with raw bytes being sent and received over a socket of some sort (UDP, TCP, and SSL being the most commonly used three). This isn't really what a SUDS/Twisted integration library is interested in. Instead, what you want is an HTTP client which SUDS can use to make the necessary requests and which presents all of the response data so that SUDS can determine what the result was. That is to say, SUDS doesn't really care about the raw bytes on the network. What it cares about is the HTTP requests and responses.

如果检查twisted.web.soap.Proxy(Twisted Web SOAP API的客户端部分)的实现,您会发现它实际上并没有做很多事情.将SOAPpy粘贴到twisted.web.client.getPage的大约20行代码.也就是说,它就是按照我上面描述的方式将SOAPpy连接到Twisted的.

If you examine the implementation of twisted.web.soap.Proxy (the client part of the Twisted Web SOAP API), you'll see that it doesn't really do much. It's about 20 lines of code that glues SOAPpy to twisted.web.client.getPage. That is, it's hooking SOAPpy in to Twisted in just the way I described above.

理想情况下,SUDS会按照SOAPpy.buildSOAPSOAPpy.parseSOAPRPC的方式提供某种API(也许这些API会更复杂,或者接受更多参数-我不是SOAP专家,所以我不知道SOAPpy的特定API是否缺少一些重要的东西-但基本思想应该相同).然后,您可以改为基于SUDS编写类似twisted.web.soap.Proxy的内容.如果twisted.web.client.getPage不能提供对请求的足够控制或有关响应的足够信息,则还可以使用twisted.web.client.Agent来代替,这是最近才引入的,可以提供对整个请求/响应过程的更多控制.但是,这再次与当前基于getPage的代码具有相同的思想,只是实现了更加灵活/更具表现力的实现.

Ideally, SUDS would provide some kind of API along the lines of SOAPpy.buildSOAP and SOAPpy.parseSOAPRPC (perhaps the APIs would be a bit more complicated, or accept a few more parameters - I'm not a SOAP expert, so I don't know if SOAPpy's particular APIs are missing something important - but the basic idea should be the same). Then you could write something like twisted.web.soap.Proxy based on SUDS instead. If twisted.web.client.getPage doesn't offer enough control over the requests or enough information about the responses, you could also use twisted.web.client.Agent instead, which is more recently introduced and offers much more control over the whole request/response process. But again, that's really the same idea as the current getPage-based code, just a more flexible/expressive implementation.

刚刚看过Client.options.transport的API文档,听起来SUDS传输基本上是HTTP客户端.这种集成的问题在于SUDS希望发送请求,然后能够立即获得响应.由于Twisted主要基于回调,因此基于Twisted的HTTP客户端API无法立即将响应返回给SUDS.它只能返回Deferred(或等效值).

Having just looked at the API documentation for Client.options.transport, it sounds like a SUDS transport is basically an HTTP client. The problem with this kind of integration is that SUDS wants to send a request and then be able to immediately get the response. Since Twisted is largely based on callbacks, a Twisted-based HTTP client API can't immediately return a response to SUDS. It can only return a Deferred (or equivalent).

这就是为什么如果关系倒置,事情会更好.与其给SUDS一个HTTP客户端,不如给SUDS和一个HTTP Client提供第三段代码,并让它们协调交互.

This is why things work better if the relationship is inverted. Instead of giving SUDS an HTTP client to play with, give SUDS and an HTTP client to a third piece of code and let it orchestrate the interactions.

通过创建基于Twisted的SUDS传输(也称为HTTP客户端)来使事情正常运行并非不可能. Twisted主要使用Deferred(aka回调)公开事件的事实并不意味着这是它只能工作的 方式.通过使用第三方库(例如greenlet),可以提供基于协程的API,其中对异步操作的请求涉及将执行从一个协程切换到另一个协程,并且通过切换回原始协程来传递事件. .有一个名为 corotwine 的项目可以做到这一点.可以使用 为SUDS提供所需的HTTP客户端API.但是,不能保证.这取决于在上下文开关突然插入之前没有的情况下,SUDS是否不中断.这是SUDS的非常微妙和脆弱的属性,在以后的发行版中,SUDS开发人员可以轻松地(无意间甚至更改)它,因此即使您可以使用它,它也不是 ideal 的理想解决方案现在就可以工作(除非您可以以承诺的形式从SUDS维护者那里得到合作,以保证可以在这种配置下测试他们的代码以确保其继续工作.)

It may not be impossible to have things work by creating a Twisted-based SUDS transport (aka HTTP client), though. The fact that Twisted primarily uses Deferred (aka callbacks) to expose events doesn't mean that this is the only way it can work. By using a third-party library such as greenlet, it's possible to provide a coroutine-based API, where a request for an asynchronous operation involves switching execution from one coroutine to another, and events are delivered by switching back to the original coroutine. There is a project called corotwine which can do just this. It may be possible to use this to provide SUDS with the kind of HTTP client API it wants; however, it's not guaranteed. It depends on SUDS not breaking when a context switch is suddenly inserted where previously there was none. This is a very subtle and fragile property of SUDS and can easily be changed (unintentionally, even) by the SUDS developers in a future release, so it's probably not the ideal solution, even if you can get it to work now (unless you can get cooperation from the SUDS maintainers in the form of a promise to test their code in this kind of configuration to ensure it continues to work).

顺便说一句,Twisted Web的SOAP支持仍基于SOAPpy且近两年未进行修改的原因是,目前还没有明显的SOAPpy替代品.有很多竞争者(

As an aside, the reason Twisted Web's SOAP support is still based on SOAPpy and hasn't been modified for nearly two years is that no clear replacement for SOAPpy has ever shown up. There have been many contenders (What SOAP client libraries exist for Python, and where is the documentation for them? covers several of them). If things ever settle down, it may make sense to try to update Twisted's built-in SOAP support. Until then, I think it makes more sense to do these integration libraries separately, so they can be updated more easily and so Twisted itself doesn't end up with a big pile of different SOAP integration that no one wants (which would be worse than the current situation, where there's just one SOAP integration module that no one wants).

这篇关于Python:如何使用Twisted作为SUDS的传输方式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆