Comment convertir un délégué VB en gestionnaire d'événements python?
Je dois réécrire le code VB suivant qui s'abonne à un délégué (événement), en python, en utilisant python.net .
Imports MtApi
Public Class Form1
Private apiClient As MtApiClient
Public Sub New()
InitializeComponent()
apiClient = New MtApiClient
AddHandler apiClient.QuoteUpdated, AddressOf QuoteUpdatedHandler
End Sub
Sub QuoteUpdatedHandler(sender As Object, symbol As String, bid As Double, ask As Double)
Dim quoteSrt As String
quoteSrt = symbol + ": Bid = " + bid.ToString() + "; Ask = " + ask.ToString()
ListBoxQuotesUpdate.Invoke(Sub()
ListBoxQuotesUpdate.Items.Add(quoteSrt)
End Sub)
Console.WriteLine(quoteSrt)
End Sub
' These can be ignored for this discussion
Private Sub btnConnect_Click(sender As System.Object, e As System.EventArgs) Handles btnConnect.Click
apiClient.BeginConnect(8222)
End Sub
Private Sub btnDisconnect_Click(sender As System.Object, e As System.EventArgs) Handles btnDisconnect.Click
apiClient.BeginDisconnect()
End Sub
End Class
Ce code VB fait partie d'une application VB pour le pont mtapi .NET.
Q: Quelle est la bonne façon de convertir ce délégué VB en un gestionnaire d'événements python?
J'ai déjà essayé de nombreuses variantes de ce qui suit:
...
import MtApi as mt
...
# apiClient_QuoteUpdated(object sender, string symbol, double bid, double ask)
def printTick(symbol, ask, bid):
print('Tick: Symbol: {} Ask: {:.5f} Bid: {:.5f}'.format(symbol, ask, bid))
class OnTick:
def __init__(self):
self.listeners = []
def __iadd__(self, listener):
# Shortcut for using += to add a listener
self.listeners.append(listener)
return self
def notify(self, *args, **kwargs):
for listener in self.listeners:
listener(*args, **kwargs)
mtc = mt.MtApiClient()
res = mtc.BeginConnect('127.0.0.1', 8222);
# This Works!
newTick = OnTick()
newTick += printTick
newTick.notify(SYM, 1.12400, 1.12300)
# This does NOT work!
newTick.notify(mtc.QuoteUpdate())
# TypeError: 'EventBinding' object is not callable
J'ai regardé les réponses ici:
- Quelle est la bonne façon de convertir cette inscription de gestionnaire d'événements de C # à VB.net?
- Les classes Python prennent-elles en charge les événements comme les autres langages?
Réponses
Comme étroitement lié à cette réponse dans une question similaire, le problème était de trop compliquer le code des délégués. Nous n'avons tout simplement pas besoin de la classe OnTick et nous sommes également conscients que le QuoteUpdatedHandler()besoin de 4 arguments , nous le remplaçons printTick(...)par cela.
(Bien sûr, si vous voulez faire quelque chose d'un peu plus compliqué ou élégant , vous voulez le créer dans une classe.)
Ensuite, le code Python équivalent à pour le délégué VB, devient:
...
def QuoteUpdatedHandler(source, sym, bid, ask) :
qstr = '{}: {:.5f} {:.5f}'.format(sym,bid,ask)
print(qstr)
...
mtc = mt.MtApiClient()
print('Connecting...')
res = mtc.BeginConnect('127.0.0.1', 8222);
# VB: AddHandler mtc.QuoteUpdated, AddressOf QuoteUpdatedHandler
# Because we want the "AddressOf" of the function, we don't use the invoking "()"
mtc.QuoteUpdated += QuoteUpdatedHandler
print('ok')
# Now run in a loop and wait for the events:
while 1:
pass
try:
time.sleep(0.1)
except KeyboardInterrupt:
print('\n Break!')
break
if (mtc.IsConnected()) :
mtc.PlaySound("tick")
mtc.BeginDisconnect()
print('\n Done!')
sys.exit(2)