I was trying to write a simple program to setup a connection between python and java using py4j. I wrote the following two lines hoping that everything would run since I'm not making any changes
from py4j.java_gateway import JavaGateway, GatewayParameters
gateway = JavaGateway(gateway_parameters=GatewayParameters(port=25335))
random = gateway.jvm.java.util.Random()
which resulted in the following error
py4j.protocol.Py4JNetworkError: An error occurred while trying to connect to the Java server (127.0.0.1:25335)
I looked around for a while and read that this might happen if java is listening on to a different port. So I wrote a for block to see what happens
for i in range(65535+1):
try:
gateway = JavaGateway(gateway_parameters=GatewayParameters(port=i))
random = gateway.jvm.java.util.Random()
print("passed port num", str(i))
except:
pass
The above block yielded nothing. None of the ports could connect. I can't figure out where I am going wrong.
How do I find the port number which the java side is using?
I am using py4j version 0.10.7 and python 3.6.0
EDIT
I have used the same java code as used in the py4j tutorial
I have a file called java_stack.java and py4j_gs.java. Both are in the same directory. I'm calling `java py4j_gs.java from the terminal. These are the contents of the two files
java_stack.java
package py4j.examples;
import py4j.GatewayServer;
public class StackEntryPoint {
private Stack stack;
public StackEntryPoint() {
stack = new Stack();
stack.push("Initial Item");
}
public Stack getStack() {
return stack;
}
public static void main(String[] args) {
GatewayServer gatewayServer = new GatewayServer(new StackEntryPoint());
gatewayServer.start();
System.out.println("Gateway Server Started");
}
}
py4j_gs.java
package py4j.examples;
import py4j.GatewayServer;
public class StackEntryPoint {
private Stack stack;
public StackEntryPoint() {
stack = new Stack();
stack.push("Initial Item");
}
public Stack getStack() {
return stack;
}
public static void main(String[] args) {
GatewayServer gatewayServer = new GatewayServer(new StackEntryPoint());
gatewayServer.start();
System.out.println("Gateway Server Started");
}
}
I also faced something same like
py4j.java_gateway:An error occurred while trying to connect to the Java server
while working on pyspark shell.
To solve this first we need to start the java geteway server.
After executing following java code my problem got resolve.
import py4j.GatewayServer;
public class Test {
public static void main(String[] args) {
Test app = new Test ();
// app is now the gateway.entry_point
GatewayServer server = new GatewayServer(app);
server.start();
}
}
Related
Sometimes it crashes after 54 seconds, sometimes 56 seconds. Output looks like:
Server started. Listening for incoming connections...
55 Received message: hello server
1/12/2023 7:38:25 AM|Fatal|WebSocket.<startReceiving>b__176_2|System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.
at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
at WebSocketSharp.Ext.<>c__DisplayClass48_0.<ReadBytesAsync>b__0(IAsyncResult ar)
I tried to add a try/catch block but I am not sure where the error is happening. I am running a websocketsharp server in c# and sending it sample data via python:
C# SERVER CODE:
using System;
using WebSocketSharp;
using WebSocketSharp.Server;
public class Echo : WebSocketBehavior
{
protected override void OnMessage(MessageEventArgs e)
{
try {
Console.WriteLine("Received message: " + e.Data);
Sessions.Broadcast(e.Data);
}
catch{
Console.WriteLine("bad happened");
}
}
}
public class Program
{
public static void Main(string[] args)
{
var wssv = new WebSocketServer(8081);
wssv.AddWebSocketService<Echo>("/Echo");
wssv.Start();
Console.WriteLine("Server started. Listening for incoming connections...");
Console.ReadLine();
wssv.Stop();
}
}
PYTHON CLIENT CODE:
import time
import websocket
def send_words(ws,words):
data = words
ws.send(data)
ws = websocket.create_connection("ws://localhost:8081/Echo")
while True:
time.sleep(1)
data = "hello server"
send_words(ws,data)
apparently its a websocket-sharp specific issue. You just have to add
wssv.KeepClean = false;
before
wssv.Start();
When the main app is running but not active the service notification click brings it to front, that's Ok.
Another case when I close the app by swiping it out from the recent apps list, the service is restarted and when I click the notification just black screen is shown and that's all.
The one interesting thing I noticed, after some time (an hour or two) it gets working - the main app is started on service notification click!
How can I achieve that once the service restarted?
The app is created with Python+Kivy and built with Buildozer and I run it on Android 10.
I tried setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) for the Intent but it didn't help.
Here is some code.
PythonService.java:
package org.kivy.android;
import android.os.Build;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import android.app.Service;
import android.os.IBinder;
import android.os.Bundle;
import android.content.Intent;
import android.content.Context;
import android.util.Log;
import android.app.Notification;
import android.app.PendingIntent;
import android.os.Process;
import java.io.File;
//imports for channel definition
import android.app.NotificationManager;
import android.app.NotificationChannel;
import android.graphics.Color;
public class PythonService extends Service implements Runnable {
// Thread for Python code
private Thread pythonThread = null;
// Python environment variables
private String androidPrivate;
private String androidArgument;
private String pythonName;
private String pythonHome;
private String pythonPath;
private String serviceEntrypoint;
// Argument to pass to Python code,
private String pythonServiceArgument;
public static PythonService mService = null;
private Intent startIntent = null;
private boolean autoRestartService = false;
public void setAutoRestartService(boolean restart) {
autoRestartService = restart;
}
public int startType() {
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (pythonThread != null) {
Log.v("python service", "service exists, do not start again");
return START_NOT_STICKY;
}
startIntent = intent;
Bundle extras = intent.getExtras();
androidPrivate = extras.getString("androidPrivate");
androidArgument = extras.getString("androidArgument");
serviceEntrypoint = extras.getString("serviceEntrypoint");
pythonName = extras.getString("pythonName");
pythonHome = extras.getString("pythonHome");
pythonPath = extras.getString("pythonPath");
boolean serviceStartAsForeground = (
extras.getString("serviceStartAsForeground").equals("true")
);
pythonServiceArgument = extras.getString("pythonServiceArgument");
pythonThread = new Thread(this);
pythonThread.start();
if (serviceStartAsForeground) {
doStartForeground(extras);
}
return startType();
}
protected int getServiceId() {
return 1;
}
protected void doStartForeground(Bundle extras) {
String serviceTitle = extras.getString("serviceTitle");
String serviceDescription = extras.getString("serviceDescription");
Notification notification;
Context context = getApplicationContext();
Intent contextIntent = new Intent(context, PythonActivity.class);
contextIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // my attempt but it didn't helped
PendingIntent pIntent = PendingIntent.getActivity(context, 0, contextIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
notification = new Notification(
context.getApplicationInfo().icon, serviceTitle, System.currentTimeMillis());
try {
// prevent using NotificationCompat, this saves 100kb on apk
Method func = notification.getClass().getMethod(
"setLatestEventInfo", Context.class, CharSequence.class,
CharSequence.class, PendingIntent.class);
func.invoke(notification, context, serviceTitle, serviceDescription, pIntent);
} catch (NoSuchMethodException | IllegalAccessException |
IllegalArgumentException | InvocationTargetException e) {
}
} else {
// for android 8+ we need to create our own channel
// https://stackoverflow.com/questions/47531742/startforeground-fail-after-upgrade-to-android-8-1
String NOTIFICATION_CHANNEL_ID = "org.kivy.p4a"; //TODO: make this configurable
String channelName = "Background Service"; //TODO: make this configurable
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName,
NotificationManager.IMPORTANCE_NONE);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.createNotificationChannel(chan);
Notification.Builder builder = new Notification.Builder(context, NOTIFICATION_CHANNEL_ID);
builder.setContentTitle(serviceTitle);
builder.setContentText(serviceDescription);
builder.setContentIntent(pIntent);
builder.setSmallIcon(context.getApplicationInfo().icon);
notification = builder.build();
}
startForeground(getServiceId(), notification);
}
#Override
public void onDestroy() {
super.onDestroy();
pythonThread = null;
if (autoRestartService && startIntent != null) {
Log.v("python service", "service restart requested");
startService(startIntent);
}
Process.killProcess(Process.myPid());
}
/**
* Stops the task gracefully when killed.
* Calling stopSelf() will trigger a onDestroy() call from the system.
*/
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
stopSelf();
}
#Override
public void run(){
String app_root = getFilesDir().getAbsolutePath() + "/app";
File app_root_file = new File(app_root);
PythonUtil.loadLibraries(app_root_file,
new File(getApplicationInfo().nativeLibraryDir));
this.mService = this;
nativeStart(
androidPrivate, androidArgument,
serviceEntrypoint, pythonName,
pythonHome, pythonPath,
pythonServiceArgument);
stopSelf();
}
// Native part
public static native void nativeStart(
String androidPrivate, String androidArgument,
String serviceEntrypoint, String pythonName,
String pythonHome, String pythonPath,
String pythonServiceArgument);
}
and the class extending PythonService:
package org.test.schedules;
import android.content.Intent;
import android.content.Context;
import org.kivy.android.PythonService;
public class ServiceService extends PythonService {
#Override
protected int getServiceId() {
return 1;
}
static public void start(Context ctx, String pythonServiceArgument) {
Intent intent = new Intent(ctx, ServiceService.class);
String argument = ctx.getFilesDir().getAbsolutePath() + "/app";
intent.putExtra("androidPrivate", ctx.getFilesDir().getAbsolutePath());
intent.putExtra("androidArgument", argument);
intent.putExtra("serviceTitle", "Schedules1106fgs_sdk28");
intent.putExtra("serviceDescription", "Service");
intent.putExtra("serviceEntrypoint", "service/main.py");
intent.putExtra("pythonName", "service");
intent.putExtra("serviceStartAsForeground", "true");
intent.putExtra("pythonHome", argument);
intent.putExtra("pythonPath", argument + ":" + argument + "/lib");
intent.putExtra("pythonServiceArgument", pythonServiceArgument);
ctx.startService(intent);
}
static public void stop(Context ctx) {
Intent intent = new Intent(ctx, ServiceService.class);
ctx.stopService(intent);
}
}
Also here is a piece of AndroidManifest.xml
<activity android:name="org.kivy.android.PythonActivity"
android:label="#string/app_name"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|fontScale|uiMode|uiMode|screenSize|smallestScreenSize|layoutDirection"
android:screenOrientation="portrait"
android:launchMode="singleTask"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="org.kivy.android.PythonService"
android:process=":pythonservice" />
<service android:name="org.test.schedules.ServiceService"
android:process=":service_service" />
Will be much appreciated for your help
Update
I haven't found the solution yet but noticed but seems the issue is related to background cached process. So if I go to Developer options -> Running services -> Show cached processes and stop the process there manually the app restarts fine.
I guess the solution could be somehow to prevent creating the cached process in the background or to kill that process at some specific moment, on app exit or service restart, I'm not an expert in Android, can anyone help with this?
I absolutely love using Node.JS for my web projects but i also love using Python at the same time, so i have been wondering, if is it possible to run Python scripts from Node, for example my Node.JS backend calls a python script to retrive some data from a SQL Database and gives it back to Node (i know i can do that all in Node but just using an example). I thought about doing it this way
1.Node creates a Json files which contains the variable the Python script will use(for example name:Jon birthDate:1996)
2.It runs a python script that reads those variables from that Json file(so it searches for Jon born in 1996)
3.It deletes the Json file when its done
4.Rinse and Repeat
Would this be a good and safe way of doing this type of thing or are there any other ways of running and "modifiying" the Python script?
I had to build a node app, but for the backend calculations, it seemed better to use NumPy and Pandas, so I did what you are doing... in the end I found an npm package called python-shell.
It works via promises, so I'd call my calculation script, and also would do some clean up with another Python script if there were any errors.
Worked pretty good. Code was something like this:
const PythonShell = require('python-shell');
router.get('/calc', (req, res) => {
PythonShell.run('py/calculate.py', {pyPath: pyPath , args: [tmpPath],}, function(err, results) {
if (err) {
PythonShell.run('py/clean_up.py', {pyPath: pyPath, args: [tmpPath2]}, function(err, results2) {
if (err) throw err;
res.json(
{
message: "error: Running clean up",
ang: 0,
vec: 0,
}
);
});
} else {
let data = JSON.parse(results);
let message = data[0];
let ang = data[1];
let vec = data[2];
res.json(
{
message: message,
ang: ang,
vec: vec,
}
);
}
});
});
I have 2 services that are defined in the same thrift file and share a port. I can use any method from serviceA no problem but whenever i try to call any of ServiceB's methods i get the exception.
this is my thrift file (service-a.thrift):
service ServiceA extends common.CommonService {
list<i64> getByIds(1: list<i64> ids)
...
}
service ServiceB extends common.CommonService {
list<i64> getByIds(1: list<i64> ids)
...
}
notes:
I'm working with a python client
Thrift version 0.8.0
Any ideas?
We had this need as well and solved by writing a new implementation of TProcessor that creates a map of multiple processors. The only gotcha is that with this implementation you need to ensure no method names overlap - i.e. don't use nice generic names like Run() in different servers. Apologies on not converting C# to Python...
Example Class:
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Thrift;
using Thrift.Protocol;
/// <summary>
/// Processor that allows for multiple services to run under one roof. Requires no method name conflicts across services.
/// </summary>
public class MultiplexProcessor : TProcessor {
public MultiplexProcessor(IEnumerable<TProcessor> processors) {
ProcessorMap = new Dictionary<string, Tuple<TProcessor, Delegate>>();
foreach (var processor in processors) {
var processMap = (IDictionary) processor.GetType().GetField("processMap_", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(processor);
foreach (string pmk in processMap.Keys) {
var imp = (Delegate) processMap[pmk];
try {
ProcessorMap.Add(pmk, new Tuple<TProcessor, Delegate>(processor, imp));
}
catch (ArgumentException) {
throw new ArgumentException(string.Format("Method already exists in process map: {0}", pmk));
}
}
}
}
protected readonly Dictionary<string, Tuple<TProcessor, Delegate>> ProcessorMap;
internal protected Dictionary<string, Tuple<TProcessor, Delegate>> GetProcessorMap() {
return new Dictionary<string, Tuple<TProcessor, Delegate>>(ProcessorMap);
}
public bool Process(TProtocol iprot, TProtocol oprot) {
try {
TMessage msg = iprot.ReadMessageBegin();
Tuple<TProcessor, Delegate> fn;
ProcessorMap.TryGetValue(msg.Name, out fn);
if (fn == null) {
TProtocolUtil.Skip(iprot, TType.Struct);
iprot.ReadMessageEnd();
var x = new TApplicationException(TApplicationException.ExceptionType.UnknownMethod, "Invalid method name: '" + msg.Name + "'");
oprot.WriteMessageBegin(new TMessage(msg.Name, TMessageType.Exception, msg.SeqID));
x.Write(oprot);
oprot.WriteMessageEnd();
oprot.Transport.Flush();
return true;
}
Console.WriteLine("Invoking service method {0}.{1}", fn.Item1, fn.Item2);
fn.Item2.Method.Invoke(fn.Item1, new object[] {msg.SeqID, iprot, oprot});
}
catch (IOException) {
return false;
}
return true;
}
}
Example Usage:
Processor = new MultiplexProcessor(
new List<TProcessor> {
new ReportingService.Processor(new ReportingServer()),
new MetadataService.Processor(new MetadataServer()),
new OtherService.Processor(new OtherService())
}
);
Server = new TThreadPoolServer(Processor, Transport);
As far as I know, there's no straightforward way to bind several services to a single port without adding this field to TMessage and recompiling thrift. If you want to have two services using the same Server, you should reimplement Thrift Server, which it doesn't seem an easy task
I have tried Qooxdoo and I made a simple Python server with SimpleXMLRPCServer, with a Python test I get the data without problems, but can I get this data from Qooxdoo? I get lost, and I've searched for 3 days but didn't get solutions.
I try this:
var JSON_lista_empresas = 1000
button1.addListener("execute", function(e)
{
var rpc = new qx.io.remote.Rpc();
rpc.setServiceName("get_data");
//rpc.setCrossDomain(true);
rpc.setUrl("http://192.168.1.54:46000");
rpc.addListener("completed", function(event)
{
console.log(event.getData());
});
rpc.callAsync( JSON_lista_empresas, '');
});
And I tried other options but got nothing :(
The link to files:
http://mieresdelcamin.es/owncloud/public.php?service=files&dir=%2Fjesus%2Ffiles%2FQooxdoo
I tried and read all of qooxdoo-contrib.
Well,
RpcPython --> Ok
and in class/qooxdoo -> test.py
run server [start-server.py] and query from webroser:
http://127.0.0.1:8000//?_ScriptTransport_id=1&nocache=1366909868006&_ScriptTransport_data={%22service%22%3A%22qooxdoo.test%22%2C%22method%22%3A%22echo%22%2C%22id%22%3A1%2C%22params%22%3A[%22Por%20fin%22]}
and the reply in webroser is:
qx.io.remote.ScriptTransport._requestFinished(1,{"error": null, "id": 1, "result": "Client said: [ Por fin ]"});
but if i query from qooxdoo like the reply is [error.png]
The code for qooxdoo:
var rpc = new qx.io.remote.Rpc( "http://127.0.0.1:8000/");
rpc.setCrossDomain( true);
rpc.setServiceName( 'qooxdoo.test');
// asynchronous call
var handler = function(result, exc) {
if (exc == null) {
alert("Result of async call: " + result);
} else {
alert("Exception during async call: " + exc+ result);
}
};
rpc.callAsync(handler, "echo", "Por fin");
I lost :((
Files in:
http://mieresdelcamin.es/owncloud/public.php?service=files&dir=%2Fjesus%2Ffiles%2FQooxdoo
Well, with Firebug this error in owncloud qx.io.remote.ScriptTransport.....is detect
¿?.............
Best Regards.
I'm guessing you confuse XML-RPC with JSON-RPC and qooxdoo only supports the latter. These protocols are similar but the data interchange format is different (XML or JSON). Instead of the SimpleXMLRPCServer you could use "RpcPython" on the server side which is a qooxdoo contrib project.
See:
http://qooxdoo.org/contrib/project/rpcpython
http://sourceforge.net/p/qooxdoo-contrib/code/HEAD/tree/trunk/qooxdoo-contrib/RpcPython/
Once you have this server up and running you should be able to test it:
http://manual.qooxdoo.org/2.1.1/pages/communication/rpc_server_writer_guide.html#testing-a-new-server
http://sourceforge.net/p/qooxdoo-contrib/code/HEAD/tree/trunk/qooxdoo-contrib/RpcPython/trunk/services/class/qooxdoo/test.py
After that your qooxdoo (client) code hopefully works also. :)
Ok,
In the file http.py of qxjsonrc module in the line 66 change
response='qx.io.remote.ScriptTransport._requestFinished(%s,%s);'%(scriptTransportID,response)
for
response='qx.io.remote.transport.Script._requestFinished(%s,%s);'%(scriptTransportID,response)
And run fine :))
This link for package modified:
http://mieresdelcamin.es/owncloud/public.php?service=files&dir=%2Fjesus%2Ffiles%2FQooxdoo
Best Regards and thanks!!!
As Richard already pointed Qooxdoo only supports its flavor of JSON-RPC.
I maintain a fork of original rpcpython called QooxdooCherrypyJsonRpc. The main goal was to hand over transport protocol to some robust framework, and leave only JSON RPC stuff. CherryPy, obviously a robust framework, allows HTTP, WSGI and FastCGI deployment. Code was refactored and covered with tests. Later I added upload/download support and consistent timezone datetime interchange.
At very minimum your Python backend may look like (call it test.py):
import cherrypy
import qxcpjsonrpc as rpc
class Test(rpc.Service):
#rpc.public
def add(self, x, y):
return x + y
config = {
'/service' : {
'tools.jsonrpc.on' : True
},
'/resource' : {
'tools.staticdir.on' : True,
'tools.staticdir.dir' : '/path/to/your/built/qooxdoo/app'
}
}
cherrypy.tools.jsonrpc = rpc.ServerTool()
if __name__ == '__main__':
cherrypy.quickstart(config = config)
Then you can do in your qooxdoo code as follows:
var rpc = new qx.io.remote.Rpc();
rpc.setServiceName('test.Test');
rpc.setUrl('http://127.0.0.1:8080/service');
rpc.setCrossDomain(true); // you need this for opening app from file://
rpc.addListener("completed", function(event)
{
console.log(event.getData());
});
rpc.callAsyncListeners(this, 'add', 5, 7);
Or open the link directly:
http://127.0.0.1:8080/service?_ScriptTransport_id=1&_ScriptTransport_data=%7B%22params%22%3A+%5B12%2C+13%5D%2C+%22id%22%3A+1%2C+%22service%22%3A+%22test.Test%22%2C+%22method%22%3A+%22add%22%7D
For more info take a look at the package page I posted above.
Richard Sternagel wrote about rpcpython. This version of rpcpython doesn't work with present version of simplejson. Becouse in json.py have incorrect import:
from simplejson.decoder import ANYTHING
from simplejson.scanner import Scanner, pattern
Improve rpcpython or use another server, for example CherryPy.