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()
当我打印堆栈时,没有关于调用者类的信息。那么是否可以在运行时检索调用者类?
【问题讨论】:
“调用者类”是什么意思。你是说a
、A
、b
还是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 <class '__main__.YourClass'>.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的主要内容,如果未能解决你的问题,请参考以下文章