java调python

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java调python相关的知识,希望对你有一定的参考价值。

参考技术A 很多朋友都想知道java怎么调python?下面就一起来了解一下吧~

java调python主要有两种方法:1.使用Runtime.getRuntime()执行脚本文件;2. 将python脚本写成进程为java提供服务,下面是具体的方法介绍:

第一种:使用Runtime.getRuntime()执行脚本文件

先建立python脚本文件 demo.py
import numpy as np a = np.arange(12).reshape(3,4)print(a)
java调用python程序并输出该结果
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;public class Demo      public static void main(String[] args)          // TODO Auto-generated method stub         Process proc;         try              proc = Runtime.getRuntime().exec("python D:\\demo.py");// 执行py文件             //用输入输出流来截取结果             BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));             String line = null;             while ((line = in.readLine()) != null)                  System.out.println(line);                          in.close();             proc.waitFor();          catch (IOException e)              e.printStackTrace();          catch (InterruptedException e)              e.printStackTrace();               
如若向python程序中函数传递参数并执行出结果,下面就举一例来说明一下。
同样建立python脚本文件demo2.py
import sys def func(a,b):     return (a+b)if __name__ == '__main__':     a = []     for i in range(1, len(sys.argv)):         a.append((int(sys.argv[i])))     print(func(a[0],a[1]))
其中sys.argv用于获取参数url1,url2等。而sys.argv[0]代表python程序名,所以列表从1开始读取参数。
以上代码实现一个两个数做加法的程序,下面看看在java中怎么传递函数参数,代码如下:
int a = 18;int b = 23;try      String[] args = new String[]  "python", "D:\\demo2.py", String.valueOf(a), String.valueOf(b) ;     Process proc = Runtime.getRuntime().exec(args);// 执行py文件     BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));     String line = null;     while ((line = in.readLine()) != null)          System.out.println(line);          in.close();     proc.waitFor(); catch (IOException e)      e.printStackTrace(); catch (InterruptedException e)      e.printStackTrace();
其中args是String[] “python”,path,url1,url2 ; ,path是python程序所在的路径,url1是参数1,url2是参数2,以此类推。

2. 将python脚本写成进程为java提供服务

python脚本文件如下:
import socketimport sysimport threadingimport numpy as npfrom PIL import Imagedef main():     # 创建服务器套接字     serversocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)     # 获取本地主机名称     host = socket.gethostname()     # 设置一个端口     port = 12345     # 将套接字与本地主机和端口绑定     serversocket.bind((host,port))     # 设置监听最大连接数     serversocket.listen(5)     # 获取本地服务器的连接信息     myaddr = serversocket.getsockname()     print("服务器地址:%s"%str(myaddr))     # 循环等待接受客户端信息     while True:         # 获取一个客户端连接         clientsocket,addr = serversocket.accept()         print("连接地址:%s" % str(addr))         try:             t = ServerThreading(clientsocket)#为每一个请求开启一个处理线程             t.start()             pass         except Exception as identifier:             print(identifier)             pass         pass     serversocket.close()     passclass ServerThreading(threading.Thread):     # words = text2vec.load_lexicon()     def __init__(self,clientsocket,recvsize=1024*1024,encoding="utf-8"):         threading.Thread.__init__(self)         self._socket = clientsocket         self._recvsize = recvsize         self._encoding = encoding        pass     def run(self):         print("开启线程.....")         try:             #接受数据             msg = ''             while True:                 # 读取recvsize个字节                 rec = self._socket.recv(self._recvsize)                 # 解码                 msg += rec.decode(self._encoding)                 # 文本接受是否完毕,因为python socket不能自己判断接收数据是否完毕,                 # 所以需要自定义协议标志数据接受完毕                 if msg.strip().endswith('over'):                     msg=msg[:-4]                     break                         sendmsg = Image.open(msg)             # 发送数据             self._socket.send(("%s"%sendmsg).encode(self._encoding))             pass         except Exception as identifier:             self._socket.send("500".encode(self._encoding))             print(identifier)             pass         finally:             self._socket.close()          print("任务结束.....")                  pass     def __del__(self):         passif __name__ == "__main__":     main()
在java代码中访问python进程的代码: package hello;import java.lang.System;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.InetAddress;import java.net.Socket;import java.io.OutputStream;import java.io.PrintStream;import java.io.InputStream;public class hello      public static void main(String[] args)         //System.out.println("Hello World!");         // TODO Auto-generated method stub         try              InetAddress addr = InetAddress.getLocalHost();             String host=addr.getHostName();             //String ip=addr.getHostAddress().toString(); //获取本机ip             //log.info("调用远程接口:host=>"+ip+",port=>"+12345);             // 初始化套接字,设置访问服务的主机和进程端口号,HOST是访问python进程的主机名称,可以是IP地址或者域名,PORT是python进程绑定的端口号             Socket socket = new Socket(host,12345);             // 获取输出流对象             OutputStream os = socket.getOutputStream();             PrintStream out = new PrintStream(os);             // 发送内容             out.print( "F:\\xxx\\0000.jpg");             // 告诉服务进程,内容发送完毕,可以开始处理             out.print("over");             // 获取服务进程的输入流             InputStream is = socket.getInputStream();             BufferedReader br = new BufferedReader(new InputStreamReader(is,"utf-8"));             String tmp = null;             StringBuilder sb = new StringBuilder();             // 读取内容             while((tmp=br.readLine())!=null)                 sb.append(tmp).append('\n');             System.out.print(sb);             // 解析结果             //JSONArray res = JSON.parseArray(sb.toString());          catch (IOException e)              e.printStackTrace();         finally              try if(socket!=null) socket.close(); catch (IOException e)              System.out.print("远程接口调用结束.");                

如何在python中另一个类的函数中获取调用者类名?

【中文标题】如何在python中另一个类的函数中获取调用者类名?【英文标题】:How to get the caller class name inside a function of another class in python? 【发布时间】:2013-06-08 12:59:06 【问题描述】:

我的目标是为此创建一个应用程序的序列图,我需要在运行时获取有关调用者和被调用者类名的信息。我可以成功检索到调用者函数但无法获取调用者类名?

#Scenario caller.py:

import inspect

class A:

    def Apple(self):
        print "Hello"
        b=B()
        b.Bad()



class B:

    def Bad(self):
        print"dude"
        print inspect.stack()


a=A()
a.Apple()

当我打印堆栈时,没有关于调用者类的信息。那么是否可以在运行时检索调用者类?

【问题讨论】:

“调用者类”是什么意思。你是说aAb还是B @mgilson 我的意思是当代码在 B 类(被调用者)下的方法“def Bad”中运行时,我必须能够打印检索调用者类的名称,即在这种情况下为“A”。 @mgilson 我可以打印“inspect.stack()[1][3]”语句,这只会让我得到调用者函数。 类似的,相关的,有趣的:get a class name of calling method 【参考方案1】:

好吧,在对提示进行了一些挖掘之后,这就是我得到的:

stack = inspect.stack()
the_class = stack[1][0].f_locals["self"].__class__.__name__
the_method = stack[1][0].f_code.co_name

print("I was called by .()".format(the_class, the_method))
# => I was called by A.a()

调用时:

➤ python test.py
A.a()
B.b()
  I was called by A.a()

给定文件test.py

import inspect

class A:
  def a(self):
    print("A.a()")
    B().b()

class B:
  def b(self):
    print("B.b()")
    stack = inspect.stack()
    the_class = stack[1][0].f_locals["self"].__class__.__name__
    the_method = stack[1][0].f_code.co_name
    print("  I was called by .()".format(the_class, the_method))

A().a()

不确定当从对象以外的东西调用时它会如何表现。

【讨论】:

做得很好。在某些时候,我想更加熟悉代码和框架对象...... 请注意,这不适用于静态或类方法,因为 self 然后不会被定义,或者它不会是类的实例(很可能) 该方法的这项工作是通过子类中的super 调用的。或者至少它不会是你所期望的,因为type(self) 将是子类的类型,而不是实际拥有该方法的类的类型。 获取调用者类的更准确方法是stack[1][0].f_locals["__class__"]。返回的是调用类,而不是第一个参数的类。 这对我来说非常有用。我只想表示诚挚的感谢。【参考方案2】:

使用Python: How to retrieve class information from a 'frame' object?的答案

我得到了这样的东西......

import inspect

def get_class_from_frame(fr):
  args, _, _, value_dict = inspect.getargvalues(fr)
  # we check the first parameter for the frame function is
  # named 'self'
  if len(args) and args[0] == 'self':
    # in that case, 'self' will be referenced in value_dict
    instance = value_dict.get('self', None)
    if instance:
      # return its class
      return getattr(instance, '__class__', None)
  # return None otherwise
  return None


class A(object):

    def Apple(self):
        print "Hello"
        b=B()
        b.Bad()

class B(object):

    def Bad(self):
        print"dude"
        frame = inspect.stack()[1][0]
        print get_class_from_frame(frame)


a=A()
a.Apple()

这给了我以下输出:

Hello
dude
<class '__main__.A'>

显然这会返回对类本身的引用。如果您想要类的名称,可以从__name__ 属性中获取。

不幸的是,这不适用于类或静态方法...

【讨论】:

这个方法实际上更完美,因为它检查“self”,如果没有则显示“None”。这正是我所需要的。【参考方案3】:

也许这破坏了某些 Python 编程协议,但如果 Bad总是 会检查调用者的类,为什么不将调用者的 __class__ 作为调用的一部分传递给它呢?

class A:

    def Apple(self):
        print "Hello"
        b=B()
        b.Bad(self.__class__)



class B:

    def Bad(self, cls):
        print "dude"
        print "Calling class:", cls


a=A()
a.Apple()

结果:

Hello
dude
Calling class: __main__.A

如果这是错误的形式,并且使用inspect 确实是获取调用者课程的首选方式,请解释原因。我仍在学习更深层次的 Python 概念。

【讨论】:

【参考方案4】:

将类实例名称从堆栈存储到类变量:

import inspect

class myClass():

    caller = ""

    def __init__(self):
        s = str(inspect.stack()[1][4]).split()[0][2:]
        self.caller = s

    def getInstanceName(self):
        return self.caller

这个

myClassInstance1 = myClass()
print(myClassInstance1.getInstanceName())

将打印:

myClassInstance1

【讨论】:

【参考方案5】:

可以使用方法inspect.currentframe() 代替索引inspect.stack() 的返回值,从而避免索引。

prev_frame = inspect.currentframe().f_back
the_class = prev_frame.f_locals["self"].__class__
the_method = prev_frame.f_code.co_name

【讨论】:

这将打印出类似I was called by &lt;class '__main__.YourClass'&gt;.your_method 的内容。要从接受的答案中获得相同的结果,请将变量 the_class 更改为 prev_frame.f_locals['self'].__class__.__name__【参考方案6】:

Python 3.8

import inspect


class B:
    def __init__(self):
        if (parent := inspect.stack()[1][0].f_locals.get('self', None)) and isinstance(parent, A):
            parent.print_coin()


class A:
    def __init__(self, coin):
        self.coin: str = coin
        B()

    def print_coin(self):
        print(f'Coin name: self.coin')


A('Bitcoin')

【讨论】:

从未想过调用方法或从调用者的类访问属性是可能的。这提供了有趣的灵活性。 @jlwise24 你说得对,这很有趣,但有时速度很慢。你必须小心,尤其是在 Python 中。阅读编程中的“内省和反思”。

以上是关于java调python的主要内容,如果未能解决你的问题,请参考以下文章

java环境 变量,python环境变量

PythonPython库之文本处理

PythonPython库之文本处理

PythonPython库之机器学习

PythonPython库之机器学习

PythonPython库之游戏开发