Pythonnet kullanarak bir python dinleyicisindeki bir .NET olayına nasıl abone olunur?

Nov 15 2020

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

3 not2qubit Nov 23 2020 at 21:56

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ür

  • QuoteUpdatedgö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
1 LOST Nov 20 2020 at 05:24

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