I create a Python webservice on Linux machine (ubuntu):
import soaplib
import os
from soaplib.core.service import rpc, DefinitionBase, soap
from soaplib.core.model.primitive import String, Integer
from soaplib.core.server import wsgi
from soaplib.core.model.clazz import Array
def runcmd(cmd):
fout = os.popen(cmd)
out = fout.read()
return out
class LinuxServices(DefinitionBase):
#soap(String, String,_returns=Array(String))
def df(self,server, user):
L = []
cmd = 'df -hP | grep "/"'
output = runcmd(cmd).split('\n')
for n in xrange(len(output)-1):
out = output[n].split()
L.append('%s;%s' % (out[5], out[4]))
return L
if __name__=='__main__':
try:
from wsgiref.simple_server import make_server
soap_application = soaplib.core.Application([LinuxServices], 'tns')
wsgi_application = wsgi.Application(soap_application)
server = make_server('0.0.0.0', 7789, wsgi_application)
server.serve_forever()
except ImportError:
print "Error: example server code requires Python >= 2.5"
I created it based on this example: soaplib helloworld
Then (on Windows 7) I created a Silverlight project, where I use this ws to get disk status on my linux server:
Service in Silverlight project:
public class LinuxService
{
[OperationContract]
public List<dfItem> df()
{
List<dfItem> dfItems = new List<dfItem>();
WebReference.Application app = new WebReference.Application();
var result = app.df(new WebReference.df()/*...*/);
foreach (var item in result.dfResult)
{
string[] info = item.Split(';');
dfItem dfItem = new dfItem()
{
MountPoint = info[0].ToString(),
Usage = info[1].ToString()
};
dfItems.Add(dfItem);
}
return dfItems;
}
//...
}
Calling service on page:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
LinuxServiceClient client = new LinuxServiceClient();
client.dfCompleted += new EventHandler<dfCompletedEventArgs>(client_dfCompleted);
client.dfAsync();
}
void client_dfCompleted(object sender, dfCompletedEventArgs e)
{
DG.ItemsSource = e.Result;
DG.Visibility = System.Windows.Visibility.Visible;
}
My problem is that when I navigate to this page, it takes 4-8 seconds to get data from ws (ws in LAN).
I really doubt that line bandwidth can create this wait time...
My question:
Do you have any suggestions what can I do to speed up this?
System Info:
UbuntuServer 11.04
Python: Python 2.7
Soaplib: soaplib 2.0.0-beta2
Windows: Windows 7 sp1
Silverlight: Silverlight 4
I'd recommend using wireshark http://www.wireshark.org/ to 'listen' in on the conversation that is occurring over the network by recording ('capturing') copies of the network traffic that the device can see.
When you start a capture, the amount of data can seem overwhelming, but if you can spot any fragments that look like your SOAP message (should be easy to spot), then you can swiftly filter to just that conversation by right-clicking and selecting 'Follow TCP Stream'.
You can then see the entire conversation between the SOAP service you've written and the silverlight client in a pop-up window.
If that all looks fine, then close the popup window. As an added bonus, wireshark will have filtered out the list of fragments to just those in the conversation with timestamps as to when they happened. Use this to find out whether it's client or server that is being slow to respond.
If there appears to be no real delay, then I would suggest that there is a considerable lag between asking Silverlight to do a SOAP call and it actually making the network call.
Just a cursory benchmark using the suds client and the soaplib hello world example:
>>> def bench_soap(num):
...: start = time.time()
...: for i in range(num):
...: hello_client.service.say_hello("Dave", 5)
...: elapsed = time.time() - start
...: print "Completed %s: ops in %.2f seconds : %.1f ops/sec" % (num, elapsed, num / elapsed)
...:
...:
>>> bench_soap(100)
Completed 100: ops in 0.40 seconds : 247.5 ops/sec
>>> bench_soap(1000)
Completed 1000: ops in 3.81 seconds : 262.5 ops/sec
I've not seen any "lag" or anything like that on my end. Soaplib, seems fast and responsive, so perhaps a Silverlight issue? Or some sort of incompatibility between the two?
Related
I created a system written in Python that provides various hardware control, data acquisition, and processing functions. I want this system to be accessible from programs written in Python or other languages, like Lua, Matlab, Octave, C++ and possibly others.
Additionally, those programs may be running either on that computer or on another machine connected via a network.
I'm aware of the existence of various RPC libraries for Python like
https://pypi.org/project/simple-rpc/ (does not offer easy interfacing with many languages)
Ice https://zeroc.com/products/ice (is too huge for my simple application)
Is there available any simple and lightweight solution enabling remote calling of Python functions from programs written in other languages?
I have developed a similar system in 2012, where the arguments to the Python functions and returned values were passed via MessagePack. Such a solution enables communication with programs written in various languages. It was published in the Usenet alt.sources group https://groups.google.com/g/alt.sources/c/QasPxJkKIUs (also available in funet archive http://ftp.funet.fi/pub/archive/alt.sources/2722.gz ).
Now I have supplemented it with ZeroMQ library that provides efficient communication with programs running either on the same or on remote machines.
The core of the system is the server written in Python:
#!/usr/bin/python3
"""
The code below implements a simple ZeroMQ and MessagePack RPC server.
Written by Wojciech M. Zabolotny, wzab<at>ise.pw.edu.pl or wzab01<at>gmail.com
13.04.2021
The code is based on a post: "Simple object based RPC for Python",
https://groups.google.com/g/alt.sources/c/QasPxJkKIUs/m/An1JnLooNCcJ
https://www.funet.fi/pub/archive/alt.sources/2722.gz
This code is published as PUBLIC DOMAIN or under
Creative Commons Zero v1.0 Universal license (whichever better suits your needs).
"""
import time
import zmq
import msgpack as mp
import traceback
import os
#Functions which process requests
def remote_mult(a,b):
return a*b
def remote_div(a,b):
print(a,b,a/b)
return a/b
def cat_file(fname):
f=open(fname,"rb")
return f.read()
#Table of functions
func={
'mult':remote_mult,
'div':remote_div,
'file':cat_file,
}
def handle(msg):
try:
obj = mp.unpackb(msg)
if len(obj) != 2:
raise Exception("Wrong number of RPC objects, should be 2: name and arguments")
if isinstance(obj[1],tuple) or isinstance(obj[1],list):
res=func[obj[0]](*obj[1])
elif isinstance(obj[1],dict):
res=func[obj[0]](**obj[1])
else:
raise Exception("Wrong type of arguments in RPC, should be list, tuple or dictionary")
res = ("OK", res)
except Exception:
res=("error", traceback.format_exc())
return mp.packb(res)
if __name__ == "__main__":
context = zmq.Context()
socket = context.socket(zmq.REP)
# Create the server, binding to localhost on port 9999
socket.bind("tcp://*:9999")
while True:
msg = socket.recv()
res = handle(msg)
socket.send(res)
The server may publish different functions with different arguments. The arguments may be given either as positional arguments (then they should be passed in a tuple) or as keyword arguments (then they should be passed as a map/dictionary).
An example of Python client using those functions is given below:
#!/usr/bin/python3
"""
The code below implements a simple ZeroMQ and MessagePack RPC client.
Written by Wojciech M. Zabolotny, wzab<at>ise.pw.edu.pl or wzab01<at>gmail.com
13.04.2021
The code is based on a post: "Simple object based RPC for Python",
https://groups.google.com/g/alt.sources/c/QasPxJkKIUs/m/An1JnLooNCcJ
https://www.funet.fi/pub/archive/alt.sources/2722.gz
This code is published as PUBLIC DOMAIN or under
Creative Commons Zero v1.0 Universal license (whichever better suits your needs).
"""
import socket
import sys
import msgpack as p
import zmq
HOST, PORT = "localhost", 9999
data = " ".join(sys.argv[1:])
objects=[
["mult",(4,5)],
["mult",{"a":7,"b":8}],
["div",{"a":9,"b":4}],
["file",("/etc/passwd",)],
["file",("/etc/non_existing_file",)],
]
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect("tcp://localhost:9999")
for obj in objects:
socket.send(p.packb(obj))
# Get the reply.
msg = socket.recv()
resp = p.unpackb(msg)
print("Received reply", resp)
Below are the clients written in other languages.
In Lua:
-- Demonstrator of the communication with simple Python RPC server from Lua
-- Written by Wojciech M. Zabołotny (wzab01<at>gmail.com or wzab<at>ise.pw.edu.pl)
-- Copyright: This program is released into the public domain or under
-- Creative Commons Zero v1.0 Universal license (whichever better suits your needs).
local zmq = require "lzmq"
--require "utils"
local mp = require "mpack"
--print_version(zmq)
local pr = require "pl.pretty"
context = assert(zmq.context())
rpcsrv = assert(context:socket (zmq.REQ))
assert(rpcsrv:connect("tcp://localhost:9999"))
function rpc(params)
local req=mp.pack(test)
rpcsrv:send(req)
local rcv=rpcsrv:recv()
local res=mp.unpack(rcv)
return res
end
test = {"file",{"/etc/passwd"}}
local res = rpc(test)
pr.dump(res)
test = {"mult",{7,8}}
res = rpc(test)
pr.dump(res)
test = {"div",{b=4.0,a=9.0}}
res = rpc(test)
pr.dump(res)
-- The above works, but 9/4 is printed as 2.
print(res[2])
test = {"div",{a=4.0,b=9.0}}
res = rpc(test)
pr.dump(res)
-- The above works, but 4/9 is printed as 0.
print(res[2])
in Octave
% Demonstrator of the communication with simple Python RPC server from Octave
% Written by Wojciech M. Zabołotny (wzab01<at>gmail.com or wzab<at>ise.pw.edu.pl)
% Copyright: This program is released into the public domain.
pkg load jsonlab
pkg load zeromq
srv = zmq_socket (ZMQ_REQ);
zmq_connect (srv, "tcp://localhost:9999");
function res = rpc(req,fname,fargs,maxlen=10000)
x={fname, fargs};
a=savemsgpack(x);
zmq_send(req,a);
w=zmq_recv(req,maxlen);
y=loadmsgpack(char(w));
if strcmp(char(y{1}),"OK")
res = y{2};
end
if strcmp(char(y{1}),"error")
error(char(y{2}));
end
endfunction
res = rpc(srv,"mult",struct("a",13,"b",20));
res
res = rpc(srv,"mult",{17,3});
res
res = rpc(srv,"file",{"/etc/passwd"});
char(res')
and finally in C++
// Demonstrator of the communication with simple Python RPC server from C++
// Written by Wojciech M. Zabołotny (wzab01<at>gmail.com or wzab<at>ise.pw.edu.pl)
// Copyright: This program is released into the public domain or under
// Creative Commons Zero v1.0 Universal license (whichever better suits your needs).
#include <string>
#include <zmq.hpp>
#include <iostream>
#include <msgpack.hpp>
msgpack::object_handle rpc(zmq::socket_t &sock, auto req)
{
std::size_t offset = 0;
std::stringstream rstr;
msgpack::pack(rstr,req);
zmq::message_t msg(rstr.str());
sock.send(msg,zmq::send_flags::none);
auto res = sock.recv(msg, zmq::recv_flags::none);
auto oh = msgpack::unpack((const char *)msg.data(),msg.size(),offset);
return oh;
}
int main(void) {
zmq::context_t ctx;
zmq::socket_t sock(ctx, zmq::socket_type::req);
sock.connect("tcp://localhost:9999");
msgpack::object_handle res;
res = rpc(sock,std::tuple<std::string, std::array<int,2>>({"mult", {7, 8}}));
std::cout << res.get() << std::endl;
res = rpc(sock,std::tuple<std::string, std::map<std::string,int>>({"div", {{"a",8},{"b",7}}}));
std::cout << res.get() << std::endl;
res = rpc(sock,std::tuple<std::string, std::map<std::string,int>>({"div", {{"b",8},{"a",7}}}));
std::cout << res.get() << std::endl;
res = rpc(sock,std::tuple<std::string, std::tuple<std::string>>({ "file", {"/etc/passwd"}}));
std::cout << res.get() << std::endl;
}
The above C++ code must be compiled with the -fconcepts-ts option e.g. like below:
c++ obj_rpc_cli.cc -o obj_rpc_cli -fconcepts-ts -g -lzmq -lmsgpackc
The solution is really minimal. The maintained version is available in the github repository: https://gitlab.com/WZab/python-versatile-rpc
I want to implement an IoT application. I will give here a toy version of what I want to do.
Say I have two clients : 'client1' and 'client2' on REMOTE COMPUTERS, and a server 'server', that regulates the computations. The hard thing for me is the fact that the computations can't be made at the same place.
We have : clients_list = ['client1', 'client2']
I want to simulate an algorithm that looks like this:
The server starts with an initial value server_value
for round in range(R):
client_values_dict = {}
for client_id in clients_list:
server broadcasts server_value to the client 'client_id' # via http
client_value = action(server_value) # executed on clients computer
client broadcasts its value to the server # via http
at the meantime, server waits for the response
server fills dictionary with keys clients_list, values client values obtained with 'action' :
client_values_dict[client_id]
server_value = aggregate(client_values_dict) # executed on server computer
On the client side (in client.py), I have a function:
import time
def action(server_value):
time.sleep(10*random.random())
return server_value + random.random()-0.5
On the server side (in server.py), I have a function:
def aggregate(client_values_dict):
return sum(client_values_dict.values())/len(client_values_dict.values())
I want to implement that : I want to write a loop at server level that performs this. I think what I need is an API to handle client-server interactions and parallel computing.
I thought of using Flask for this but I'm afraid that the loop at server level will be blocked by the app.run(debug=True) loop, and that my code won't run until I break the app with CTRL+C.
I want the computations to be made in parallel by the two clients.
I am not familiar with web developpement, my problem might seem trivial and help is probably to be found everywhere on internet, but I don't know where to look at. Any help is cheerfully welcomed.
Here is an example ofa script that simulates what I want, but online.
# -*- coding: utf-8 -*-
import time
import random
server_value = 0
R = 10
clients_list = ['client1', 'client2']
def action(server_value):
time.sleep(3*random.random())
return server_value + random.random()-0.5
def aggregate(client_values_dict):
return sum(client_values_dict.values())/len(client_values_dict.values())
for round in range(R):
client_values_dict = {}
for client_id in clients_list:
client_value = action(server_value) # executed on clients computer
client_values_dict[client_id] = client_value
server_value = aggregate(client_values_dict)
print(server_value)
Have you tried network zero? It's an amazing networking library that I use all the time.
Install:
pip install networkzero
PyPI link: https://pypi.org/project/networkzero/
Docs: https://networkzero.readthedocs.io/en/latest/
Code sample (from their doc page):
Machine/process A:
import networkzero as nw0
address = nw0.advertise("hello")
while True:
name = nw0.wait_for_message_from(address)
nw0.send_reply_to(address, "Hello " + name)
Machine/process B:
import networkzero as nw0
hello = nw0.discover("hello")
reply = nw0.send_message_to(hello, "World!")
print(reply)
reply = nw0.send_message_to(hello, "Tim")
print(reply)
This library also supports more than just 2 connections on the local WiFi, read the docs for more info.
NOTE: I've used this answer before. You can see it here: How to set up a server for a local wifi multiplayer game for python
I currently try to set up a plain Push-Pull-Socket architecture using zeroMQ whereas Metatrader 4 (MQL) acts as publisher and my Python backend acts as consumer.
I push data from Metatrader 4 terminal every second which works just fine. However, I'm having tough times to receive data on the pull socket. Once I try to pull that data out of the wire the atom script package raises the error address already in use.
I run both the MT 4 terminal and the Python script on my local machine while in development.
Metatrader 4:
extern string PROJECT_NAME = "Dashex.Feeder";
extern string ZEROMQ_PROTOCOL = "tcp";
extern string HOSTNAME = "*";
extern int PUSH_PORT = 32220;
extern string t0 = "--- Feeder Parameters ---";
input string DID = "insert your DID here";
extern string t1 = "--- ZeroMQ Configuration ---";
extern bool Publish_MarketData = false;
// ZeroMQ environment //
// CREATE ZeroMQ Context
Context context(PROJECT_NAME);
// CREATE ZMQ_PUSH SOCKET
Socket pushSocket(context, ZMQ_PUSH);
string Publish_Symbols[7] = {
"EURUSD","GBPUSD","USDJPY","USDCAD","AUDUSD","NZDUSD","USDCHF"
};
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
EventSetTimer(1); // Set Millisecond Timer to get client socket input
context.setBlocky(false);
// Send responses to PULL_PORT that client is listening on.
Print("[PUSH] Connecting MT4 Server to Socket on Port " + IntegerToString(PUSH_PORT) + "..");
pushSocket.connect(StringFormat("%s://%s:%d", ZEROMQ_PROTOCOL, HOSTNAME, PUSH_PORT));
pushSocket.setSendHighWaterMark(1);
pushSocket.setLinger(0);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
Print("[PUSH] Disconnecting MT4 Server from Socket on Port " + IntegerToString(PUSH_PORT) + "..");
pushSocket.disconnect(StringFormat("%s://%s:%d", ZEROMQ_PROTOCOL, HOSTNAME, PUSH_PORT));
// Shutdown ZeroMQ Context
context.shutdown();
context.destroy(0);
EventKillTimer();
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTimer()
{
/*
Use this OnTimer() function to send market data to consumer.
*/
if(!IsStopped() && Publish_MarketData == true)
{
for(int s = 0; s < ArraySize(Publish_Symbols); s++)
{
// Python clients can subscribe to a price feed by setting
// socket options to the symbol name. For example:
string _tick = GetBidAsk(Publish_Symbols[s]);
Print("Sending " + Publish_Symbols[s] + " " + _tick + " to PUSH Socket");
ZmqMsg reply(StringFormat("%s %s", Publish_Symbols[s], _tick));
pushSocket.send(reply, true);
}
}
}
//+------------------------------------------------------------------+
string GetBidAsk(string symbol) {
MqlTick last_tick;
if(SymbolInfoTick(symbol,last_tick))
{
return(StringFormat("%f;%f", last_tick.bid, last_tick.ask));
}
// Default
return "";
}
Pushing data works as intended:
Python based pull socket:
import zmq
import time
context = zmq.Context()
zmq_socket = context.socket(zmq.PULL)
zmq_socket.bind("tcp://*:32220")
time.sleep(1)
while True:
result = zmq_socket.recv()
print(result)
time.sleep(1)
This is what script reports in the console:
Netstat output:
Note: When I terminate both the Metatrader push script and the python script the port is still marked as "listened" in netstats. When I change the port to 32225 (or any other) in both instances and re-run them, I get the same error again. If I first run the pull instance I have a sandglass popping up in atom script, when I then run the MT4 push instance nothing happens on the pull side. When I then re-run the pull instance I get the same error again.
Update:
The python.exe instance in the background occupied the port. I shut down the python execution and the port was released again. When I now run my pull instance i receive the following console feedback:
1.)
2.)
I then run the push instance which works just fine.
3.)
The pull instance still shows the sandglass and doesn't print any data into the console:
4.)
When I then re-run the pull instance it raises the error address in use which now makes sense since Python uses that port still in the background.
But why isn't any data printed on the pull side? Do I have to change the pull client code in order to be able to "grab" the pushed data?
The problem is with your PUSH code, here:
extern string HOSTNAME = "*";
While you can legitimately use * for the hostname component in a bind URL (in which case it means "listen on all addresses"), it doesn't make any sense in a connect call: you must provide a valid hostname or ip address.
If you were to modify your code to read:
extern string HOSTNAME = "localhost";
It would probably work as expected.
Here's a simple Python PUSH client I used to test your PULL code; if you run this and run your PULL code (as posted in your question), it all works:
import time
import zmq
c = zmq.Context()
s = c.socket(zmq.PUSH)
s.connect('tcp://localhost:32220')
i = 0
while True:
s.send_string('this is message {}'.format(i))
i += 1
time.sleep(0.5)
I've made a python program in Raspberry Pi 3 Model B that's supposed to connect to Google Cloud IoT Core with MQTT-protocol and get configurations. Sending data to Core has worked so far, but I just can't figure out how configuring works! Here's a code that's just supposed to get a config:
import time
import datetime
import jwt
import ssl
import json
import paho.mqtt.client as mqtt
time_now = datetime.datetime.utcnow()
#make key
token = {'iat' : time_now ,
'exp' : time_now + datetime.timedelta(minutes=60),
'aud' : "[PROJECT]"}
r = open("[PRIVATE KEY]", 'r')
pub_key = r.read()
jwt_key = jwt.encode(token, pub_key, algorithm='RS256')
#connect to iot-core
client = mqtt.Client(client_id='projects/[PROJECT]/locations/[LOCATION]/registries/[REGISTER]/devices/[DEVICE]')
client.username_pw_set(username='unused', password=jwt_key)
client.tls_set(ca_certs='/home/pi/.local/lib/python2.7/site-packages/grpc/_cython/_credentials/roots.pem', tls_version=ssl.PROTOCOL_TLSv1_2)
client.connect("mqtt.googleapis.com", 8883)
#configure and change state
state = 0
print state #naturally shows 0
print client.subscribe([DEVICE]/config, qos=1) #doesn't print custom config either, just (0,1)
print state #still shows 0
configuration in Iot Core device id is:
{ "state": 1 }
Even after running the program, the device's "state"-variable stays at 0 and the Core's Configuration & State History state that the CONFIG is "Not yet acknowledged by the device"
How do I get the device's "state" variable change from 0 to 1 from Core?
You have done the half of the job. 2 remarks.
It's maybe a detail, but you name your private key pub_key. And you don't close the file.
Based on this tutorial, you only subscribe to the MQTT. The return tuple (0,1) means MQTT_ERR_SUCCESS on QOS = 1. Thus your are connected. Great! Now, do the second part: consume the messages in the channel, and make your logic (according with the received message, change the state in your app if it's your use case)
I want an Expert Advisor to open an Trade triggerd by a Telegram-Message.
I succesfully set up an Hello-World application using MQ4 as Server and Python/Telegram-bot as Client.
When the Telegram-Bot recieves a Message, he will send a request to MQ4 and gets a simple response without executing a trade.
Running Code below.
# Hello World client in Python
# Connects REQ socket to tcp://localhost:5555
import zmq
context = zmq.Context()
# Socket to talk to server
print("Connecting to trading server…")
socket = context.socket(zmq.REQ)
socket.connect("tcp://localhost:5555")
print("Connecting to trading server succeed")
#################################################################################
# Use your own values from my.telegram.org
api_id = ######
api_hash = '#####'
bot_token = '#####'
#################################################################################
from telethon import TelegramClient, events
client = TelegramClient('anon', api_id, api_hash)
#client.on(events.NewMessage)
async def my_event_handler(event):
if "Ascending" in event.raw_text:
if "AUDUSD" in event.raw_text:
await event.reply("AUDUSD sell")
# Do 1 request, waiting for a response
for request in range(1):
print("Telegram: AUDUSD sell execution requested %s …" % request)
socket.send(b"AUDUSD Sell execute")
#Send 2 variables (Ordertype // Symbol)
# Get the reply. -> Not neccesary for final application
# Apülication just needs to send 2 Varianles to MQ4 and trigger the open_order()
message = socket.recv()
print("Received reply %s [ %s ]" % (request, message))
client.start()
client.run_until_disconnected()
// Hello World server in MQ4
#include <Zmq/Zmq.mqh>
//+------------------------------------------------------------------+
void OnTick()
{
Context context("helloworld");
Socket socket(context,ZMQ_REP);
socket.bind("tcp://*:5555");
while(!IsStopped())
{
ZmqMsg request;
// Wait for next request from client
// MetaTrader note: this will block the script thread
// and if you try to terminate this script, MetaTrader
// will hang (and crash if you force closing it)
socket.recv(request);
Print("Receive: AUDUSD Sell execute");
Sleep(1000);
ZmqMsg reply("Trade was executed");
// Send reply back to client
socket.send(reply);
Print("Feedback: Trade was executed");
}
}
//+------------------------------------------------------------------+
Now I want to send 2 variables from Python to MQ4.
1. Ordertype: buy/sell
2. Symbol: EURUSD, AUDUSD,...
Send "Sell" if message contains "Ascending" -
Send "Buy" if message contains "Descending"
Send "AUDUSD" if message contains "AUDUSD",...
To do so I found a Library from Darwinex and want to combine it (interpretation of message, sending value as an array) with my already functioning telegram-bot.
For testing I wanted to try the example-code from Darwinex by itself.
I found the Code v2.0.1:
Python:
https://github.com/darwinex/DarwinexLabs/blob/master/tools/dwx_zeromq_connector/v2.0.1/Python/DWX_ZeroMQ_Connector_v2_0_1_RC8.py
MQ4: (Note: This Library code may replace the whole MQ4 code above in final app.)
https://github.com/darwinex/DarwinexLabs/blob/master/tools/dwx_zeromq_connector/v2.0.1/MQL4/DWX_ZeroMQ_Server_v2.0.1_RC8.mq4
When I copy the Code without changing I get an error in Python:
NameError: name '_zmq' is not defined
After running: _zmq._DWX_ZeroMQ_Connector() - in the Kernel of Spyder.
What can I do to fix that error?
In the final state I want to run the Python-Code and the Expert Advisor on the same Windows Server 2012 R2.
Is it enough if I run the .py file in the powershell from the server or should I host the file with the Webside?
I expect to get the whole system/examplecode running on my VPS or Webside-Host-Server and get an testing environment for further coding action, but currenty I cant get the Library Code in Python to run properly.
Also the MT4 ceeps crashing with the current code - but should be fixed if I combine my application with the Library-Codeexample.
(running everything on my local PC with WIN 10).
Q : I think it is a connection-problem between MT4 and Python.
Without a fully reproducible MCVE-code this is undecideable.
Having used a ZeroMQ-based bidirectional signalling/messaging between a QuantFX in python and trading ecosystem MetaTrader 4 Terminal implemented in MQL4, there is a positive experience of using this architecture.
Details decide.
The Best Next Step :
Start with a plain PUSH/PULL archetype python-PUSH-es, MQL4-script-PULL-s, preferably using tcp:// transport-class ( win platforms need not be ready to use an even simpler, protocol-less, ipc:// transport-class.
Once you have posack'd this trivial step, move forwards.
Q : How do I need to setup my Server to get a connection betwen those two - since it should be the same as on my local PC?
It is normal to use ZeroMQ on the same localhost during prototyping, so you may test and debug the integration. For details on ZeroMQ, feel free to read all details in other posts.
Q : Is it enough if I run the .py file in the powershell from the server or should I host the file with the Webside I already have and use that as "Python-Server"?
Yes, in case the .py file was designed that way. No code, no advice. That simple.
Possible issues :
Versions - ZeroMQ, since 2.11.x till the recent 4.3.+, has made a lot of changes
Installation DLL-details matter.
MQL4 has similarly gone through many changes ( string ceased to be a string and become struct to name a biggest impacting one ), so start with simple scenarios and integrate the target architecture in steps / phases with due testing whether the completed phases work as expected.
to fix that problem you need this:
from DWX_ZeroMQ_Connector_v2_0_1_RC8 import DWX_ZeroMQ_Connector
_zmq = DWX_ZeroMQ_Connector()
(adjust your version of the connector as appropriate).
should fix that problem.