gpt4 book ai didi

python - 扭曲矩阵回调调用一次又一次

转载 作者:行者123 更新时间:2023-11-30 23:32:47 25 4
gpt4 key购买 nike

我需要当用户单击一个按钮时,该按钮会触发回调并向她传递一些参数,每次参数都将不同。

我看过文档,但似乎缺少循环部分:

Looping

A common form of dependency is needing to perform the asynchronous operation all over again. The canonical example of this an HTTP redirect: when the callback for a deferred from a page request is returned, it could be the result, or it could be an empty body with the Location HTTP header set, in which case you simply perform the operation over again.

[ here is the HTTP redirect example. It also should have pictures. ]


如果工作正常,也可以尝试,但回调仅运行一次

 if happen this:
try:
print "I'm here!"
myobjectx.addCallback(test,x,y,z)
myobjectx.callback()

except:
...


只是为了了解如何工作:

1) create the myobject that do  nothing for now 
2) when an event is fired prepare the callback for the myobject e execute it
3) how can I redo the callback next time the event happen again?


我正在看异步客户端的pymodbus库示例:

https://pymodbus.readthedocs.org/en/latest/examples/asynchronous-client.html

我有2个文件:

MAINPROCESS
MODBUSLIB


从MAINPROCESS我打电话

myobjectx = MODBUSLIB.protocol.ClientCreator(reactor, ModbusClientProtocol
).connectTCP("localhost", Defaults.Port)


然后在由if触发的函数中:

if ('Gigiisclicked' in existkeys):

myobjectx.addCallback(beginAsynchronousTest)
myobjectx.callback(beginAsynchronousTest)
print "executed"


这是,当事件发生但回调号为no时,一次又一次重复打印。

最佳答案

我认为这里的一个误解是有关如何使用Deferred实例的。

您应该将Deferred视为具有两种不同的(尽管高度相关)用途。

一种用途是能够从知道如何注意到事件已发生的某些代码中发布事件到可能对知道该事件已发生有兴趣的其他代码中。

此用法的一个示例是ClientCreator.connectTCP:此API的实现知道TCP连接尝试成功(或失败)的时间,并使用Deferred将此信息发布到其他代码。像这样使用Deferred的代码实际上是实例化Deferred的代码(例如d = Deferred()),后来又使用Deferred.callbackDeferred.errback

Deferred的另一种用法是允许对发生的事件感兴趣的代码了解这些事件已发生。例如,您的该应用程序需要TCP连接以交换数据-但需要等待一个正在建立的应用程序才能继续进行。像这样使用Deferred的代码是使用Deferred.addCallbackDeferred.addErrback的代码(在最新版本的Twisted中也为Deferred.cancel)。

Deferred.addCallback是用于指定Deferred最终获得结果时要运行什么代码的API。

Deferred.callback是用于将结果提供给Deferred的API。而且,重要的是,只能给Deferred一个结果。每个Deferred实例代表单个操作的完成或单个事件的发生。

有某些例外情况和其他一些细微之处,但一个很好的经验法则是,如果您的代码未实例化Deferred,则您的代码不应使用其callback(或errback)方法。对于创建Deferred的任何代码,调用其中之一是工作。

鉴于此,我希望很明显在此代码中使用Deferred API时需要解决一些问题:

myobjectx = MODBUSLIB.protocol.ClientCreator(reactor, ModbusClientProtocol
).connectTCP("localhost", Defaults.Port)

...

if ('Gigiisclicked' in existkeys):

myobjectx.addCallback(beginAsynchronousTest)
myobjectx.callback(beginAsynchronousTest)
print "executed"


最直接的是,您不应在此处调用 myobjectx.callback。这是 ClientCreator.connectTCP的工作(最重要的是, beginAsynchronousTest可能没有意义)。

相反,我认为您想使用 Deferred最终为您创建的 ModbusClientProtocol实例的方法。在链接到的示例中,请注意, ClientCreator.connectTCP被定义为接受一个名为 beginAsynchronousTest的参数。

由于将 client传递给 beginAsynchronousTest返回的 addCallbackDeferred方法,这意味着将使用初始化 ClientCreator.connectTCP的协议实例(在这种情况下为 ClientCreator)调用该方法。 。通过实施 ModbusClientProtocolbeginAsynchronousTest提供结果后,将立即调用 Deferred-换句话说,建立连接后将立即调用它。建立TCP连接需要花费一些时间,因为它涉及到通过任意网络链接与任意其他计算机交换数据-无法确定这些资源将花费多长时间来完成其部分连接设置。

调用 ClientCreator后,您将建立连接-由传递给它的 beginAsynchronousTest实例表示。这是程序中可以开始执行多项操作(例如,每次单击按钮时执行的操作)的要点。

至此,您的程序开始使用的 ModbusClientProtocol(在上面的代码片段中称为 Deferred)已经完成,不再有用或有趣,因此您将不再使用它。

相反,您将调用 myobjectx的方法( ModbusClientProtocolread_coils或您要执行的其他任何操作)。这些方法中的每一个都可能返回代表该特定操作结果的全新 write_coil。您需要对它们使用 Deferred以便了解其结果。

人们经常迷失的另一个地方是弄清楚如何进行这些附加的方法调用。如果要将代码添加到 addCallback的正文中,则如何执行此操作非常简单:

reading = client.read_coils(1, 1)


但是,我怀疑您不想将按钮处理代码添加到 beginAsynchronousTest的正文中。取而代之的是,您可能在程序中的其他任何地方都有一个事件处理程序,该事件处理程序在每次按下按钮时都会被调用。幸运的是,处理这种情况并不复杂。

关键是要记住,只要您有对连接的引用,就可以使用它。在 beginAsynchronousTest主体内,您可以引用它- beginAsynchronousTest参数。您也可以使该引用对程序的其他部分可用:在由程序的必要部分共享的对象上设置属性是一种常见的,相当好的方法。

class ButtonModbusSomething(object):
def __init__(self):
self.client = None

def connect(self):
creator = MODBUSLIB.protocol.ClientCreator(reactor, ModbusClientProtocol)
connecting = creator.connectTCP("localhost", Defaults.Port)
connecting.addCallback(self._connected)
connecting.addErrback(log.err)

def _connected(self, client):
self.client = client

def buttonClicked(self, existkeys):
if self.client is not None:
if "Gigiisclicked" in existkeys:
self.client.read_coil(1, 1)


请注意, clientclient属性是如何以 ButtonModbusSomething开头的,以及 None需要如何检查这种情况。如上所述,建立连接可能要花费一些时间,并且唯一知道等待 buttonClicked的时间的方法是等待调用。此检查可确保如果在连接存在之前单击了按钮,则事件将被忽略(您可能希望更好地处理该事件-例如,通过从处于禁用状态的用户界面开始,然后仅在连接已建立)。

另外,我省略了您可能还想处理丢失的连接的代码。发生这种情况时, _connected属性不再有用。它仍然是对已连接的 client的引用,但是由于该协议实例不再具有连接,因此很难做任何有用的事情。当连接断开或至少开始再次忽略按钮按下时,您可能需要重新禁用用户界面。

另外,请注意 ModbusClientProtocol实际上来自 ClientCreator而不是 twisted.internet.protocol

关于python - 扭曲矩阵回调调用一次又一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19223972/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com