Pythonnet kullanarak bir python dinleyicisindeki bir .NET olayına nasıl abone olunur?
Python kullanarak bir FX ticaret uygulamasından bir tick (fiyat) olayına abone olmak için bir olay dinleyicisi yapmaya çalışıyorum . Orijinal uygulama, MetaTrader4 adlı yerel bir 32 bit Windows uygulamasıdır . Bunun herhangi bir API'si yoktur, bu nedenle mtapi köprüsü, diğer programlama dillerinin onunla etkileşime girmesine izin vermek için .NET'te tasarlanmıştır. Uygulama, ikisi: QuoteUpdateve olmak üzere tanımlanmış bazı olaylara sahiptir QuoteUpdated.
Bu nedenle , bu etkinliğe abone olmak için python.net kullanarak bir dinleyici ( temsilci ) yazmak istiyorum . Ancak .NET kodunun bu olayları nasıl ürettiğini ve pythonnet'i nasıl düzgün kullanacağımı anlayamadığım için , bunu çalıştırmayı başaramadım. Ayrıca hatayla karşılaşmaya devam ediyorum:
TypeError: 'EventBinding' object is not callable
Googling, bu "FIXME" yorumu dışında yararlı bir şey döndürmez .
İşte kodum:
import os, sys, clr
sys.path.append(r"C:\Program Files\MtApi")
asm = clr.AddReference('MtApi')
import MtApi as mt
res = 0
def printTick(symbol, ask, bid):
print('Tick: Symbol: {} Ask: {:.5f} Bid: {:.5f}'.format(symbol, ask, bid))
# Setup .NET API bridge connection
mtc = mt.MtApiClient()
res = mtc.BeginConnect('127.0.0.1', 8222);
#--------------------------------------
# Register and use the listener
#--------------------------------------
# This does NOT work!
mtc.QuoteUpdate += printTick
#...
Kodumun amacı açık olmalı.
S: QuoteUpdate.NET olayını alırken dinleyicimin ateşlenmesini nasıl sağlayabilirim ?
Referans için:
- C # ' teki .NET kodu ( MtApiClient.cs’den şuna benzer:
...
private void _client_QuoteUpdated(MTApiService.MtQuote quote) {
if (quote != null) {
QuoteUpdate?.Invoke(this, new MtQuoteEventArgs(new MtQuote(quote)));
QuoteUpdated?.Invoke(this, quote.Instrument, quote.Bid, quote.Ask);
}
}
...
public event MtApiQuoteHandler QuoteUpdated;
public event EventHandler<MtQuoteEventArgs> QuoteUpdate;
public event EventHandler<MtQuoteEventArgs> QuoteAdded;
public event EventHandler<MtQuoteEventArgs> QuoteRemoved;
- Ve küçük bir VB Test uygulaması şuna benzer:
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
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
GÜNCELLEME
Referans için, öznitelikler, türler ve aşağıdaki ilgili DLL çağrılarına sahibiz __doc__:
attr: QuoteAdded type: <class 'CLR.EventBinding'> doc: <n/a>
attr: QuoteRemoved type: <class 'CLR.EventBinding'> doc: <n/a>
attr: QuoteUpdate type: <class 'CLR.EventBinding'> doc: <n/a>
attr: QuoteUpdated type: <class 'CLR.EventBinding'> doc: <n/a>
attr: add_QuoteAdded type: <class 'CLR.MethodBinding'> doc: Void add_QuoteAdded(System.EventHandler`1[MtApi.MtQuoteEventArgs])
attr: add_QuoteRemoved type: <class 'CLR.MethodBinding'> doc: Void add_QuoteRemoved(System.EventHandler`1[MtApi.MtQuoteEventArgs])
attr: add_QuoteUpdate type: <class 'CLR.MethodBinding'> doc: Void add_QuoteUpdate(System.EventHandler`1[MtApi.MtQuoteEventArgs])
attr: add_QuoteUpdated type: <class 'CLR.MethodBinding'> doc: Void add_QuoteUpdated(MtApi.MtApiQuoteHandler)
attr: remove_QuoteAdded type: <class 'CLR.MethodBinding'> doc: Void remove_QuoteAdded(System.EventHandler`1[MtApi.MtQuoteEventArgs])
attr: remove_QuoteRemoved type: <class 'CLR.MethodBinding'> doc: Void remove_QuoteRemoved(System.EventHandler`1[MtApi.MtQuoteEventArgs])
attr: remove_QuoteUpdate type: <class 'CLR.MethodBinding'> doc: Void remove_QuoteUpdate(System.EventHandler`1[MtApi.MtQuoteEventArgs])
attr: remove_QuoteUpdated type: <class 'CLR.MethodBinding'> doc: Void remove_QuoteUpdated(MtApi.MtApiQuoteHandler)
Benzer Sorunlar:
Kelimenin tam anlamıyla 100'lerce ilgili SO sorunu var ve bunların% 60'ından fazlasına baktım, ancak kullanım durumuna göre uygulanabilirliğe neredeyse sıfır başarı ile. Bunlardan bazıları:
- Python sınıfları diğer diller gibi olayları destekliyor mu?
- Bu olay işleyici kaydını C #'dan VB.net'e dönüştürmenin doğru yolu nedir?
- Bir VB temsilcisini bir python olay işleyicisine nasıl dönüştürebilirim?
- https://ironpython.net/documentation/dotnet/dotnet.html (aynı zamanda alakalı olabilir)
- https://openbookproject.net/thinkcs/python/english3e/events.html
- https://code.activestate.com/recipes/410686-c-style-events-in-python/
Yanıtlar
Birkaç gün ve birkaç uzun saatten sonra bir hata kombinasyonu buldum. Her zaman olduğu gibi, 2-3 basit hatanın birleşimi hayatınızı uzun süre perişan edebilir. Ancak en büyük hata, bir dinleyicinin (diğer bir deyişle, temsilcinin ) bir grup __init__ve __iadd__işlevle karmaşık olması gerektiğini düşünerek kandırılmaktı . Yanlış! Python.NET çoğu zaman çalışır, ancak herhangi bir küçük hata yaparsanız, aldığınız hatalar (varsa) oldukça işe yaramaz.
Orijinal kodumla ilgili 1.5 sorun var.
2 farklı Alıntı işlevi vardı :
QuoteUpdategönderen ve .NET'te "MtQuoteEventArgs" adlı bir nesne döndürürQuoteUpdatedgönderen ve 3 bağımsız değişken döndürür .Bu nedenle hem printTick () işlevini hem de dinleyici satırını düzeltmemiz gerekir .
Düzeltilen kod:
def printTick(source, symbol, ask, bid):
print('Tick: Symbol: {} Ask: {:.5f} Bid: {:.5f}'.format(symbol, ask, bid))
...
mtc.QuoteUpdates += printTick
C # etkinlikleri ve temsilcileriyle ilgili ek bilgi için :
- https://www.tutorialsteacher.com/csharp/csharp-event
Bağladığınız mtapi belgelerine göre kod şu şekilde olmalıdır:
def printTick(sender, args):
print(str(args.Quote.Instrument))
mtc = mt.MtApiClient()
res = mtc.BeginConnect('127.0.0.1', 8222)
mtc.QuoteUpdate += printTick # Subscribe & handle new repeated events
rA = mtc.SymbolInfoTick(SYM) # Make a request to get a one-time tick data
# Need wait loop here