Gọi Python trong Java?


Câu trả lời:


101

Jython: Python cho Nền tảng Java - http://www.jython.org/index.html

Bạn có thể dễ dàng gọi các hàm python từ mã Java với Jython. Điều đó miễn là bản thân mã python của bạn chạy trong jython, tức là không sử dụng một số tiện ích mở rộng c không được hỗ trợ.

Nếu điều đó phù hợp với bạn, đó chắc chắn là giải pháp đơn giản nhất mà bạn có thể nhận được. Nếu không, bạn có thể sử dụng org.python.util.PythonInterpretertừ hỗ trợ trình thông dịch Java6 mới.

Một ví dụ đơn giản từ đỉnh đầu của tôi - nhưng sẽ hiệu quả, tôi hy vọng: (không kiểm tra lỗi được thực hiện cho ngắn gọn)

PythonInterpreter interpreter = new PythonInterpreter();
interpreter.exec("import sys\nsys.path.append('pathToModules if they are not there by default')\nimport yourModule");
// execute a function that takes a string and returns a string
PyObject someFunc = interpreter.get("funcName");
PyObject result = someFunc.__call__(new PyString("Test!"));
String realResult = (String) result.__tojava__(String.class);

Tôi đã cài đặt JYthon, hoặc tôi cho rằng tôi đã làm, và tôi tiếp tục cố gắng chạy mã mà bạn đã vạch ra nhưng nó được đánh dấu là một lỗi. Quá trình cài đặt Jython có cần đi đến một thư mục cụ thể, trong thư mục python hoặc java không?
Shahab

2
Không có bất kỳ lỗi, tôi chỉ có một thời gian khó tích hợp Jython vào Netbeans
Shahab

Nếu không có lỗi, nó sẽ hoạt động, vì vậy rõ ràng không phải vậy;) "Lỗi" không có nghĩa là lỗi thời gian chạy, cũng có thể là lỗi biên dịch.
Voo

Tệ của tôi, đó là một cách sử dụng từ kém. Tôi đang cố gắng thêm jython.jar vào dự án và netbeans của mình. I figured it out mặc dù
Shahab

1
Python 2 end of Life là 1.1.2020 và Jython chỉ hỗ trợ Python 2.7. vì vậy không có Jython về cơ bản là chết. Tốt nhất (đơn giản nhất) Lựa chọn là Jep lib
garyee

63

Này, tôi nghĩ tôi sẽ nhập câu trả lời của mình cho điều này mặc dù nó đã muộn. Tôi nghĩ rằng có một số điều quan trọng cần xem xét đầu tiên với mức độ mạnh mẽ mà bạn muốn có liên kết giữa java và python.

Trước hết Bạn chỉ muốn gọi các hàm hay bạn thực sự muốn mã python thay đổi dữ liệu trong các đối tượng java của mình? Cái này rất quan trọng. Nếu bạn chỉ muốn gọi một số mã python có hoặc không có đối số, thì điều đó không khó lắm. Nếu các lập luận của bạn là sơ khai, nó thậm chí còn dễ dàng hơn. Tuy nhiên, nếu bạn muốn lớp java thực hiện các hàm thành viên trong python, hàm này thay đổi dữ liệu của đối tượng java, thì điều này không dễ dàng hoặc dễ dàng.

Thứ hai là chúng ta đang nói về cpython hay sẽ làm jython? Tôi sẽ nói cpython là nơi của nó tại! Tôi sẽ ủng hộ đây là lý do tại sao python rất khôngol! Tuy nhiên, có tính trừu tượng cao như vậy có thể truy cập vào c, c ++ khi cần thiết. Hãy tưởng tượng nếu bạn có thể có điều đó trong java. Câu hỏi này thậm chí không đáng để hỏi liệu jython có ổn không vì dù sao thì nó cũng dễ dàng.

Vì vậy, tôi đã chơi với các phương pháp sau và liệt kê chúng từ dễ đến khó:

Java sang Jython

Ưu điểm: Dễ dàng. Có tham chiếu thực tế đến các đối tượng java

Nhược điểm: Không có CPython, Cực kỳ chậm!

Jython từ java quá dễ dàng, và nếu điều này thực sự đủ thì tuyệt vời. Tuy nhiên nó rất chậm và không có cpython! Cuộc sống có đáng sống không khi không có cpython Tôi không nghĩ vậy! Bạn có thể dễ dàng có mã python triển khai các chức năng thành viên của bạn cho các đối tượng java.

Java sang Jython đến CPython qua Pyro

Pyro là mô-đun đối tượng từ xa cho python. Bạn có một số đối tượng trên trình thông dịch cpython và bạn có thể gửi cho nó các đối tượng được chuyển qua tuần tự hóa và nó cũng có thể trả về các đối tượng thông qua phương thức này. Lưu ý rằng nếu bạn gửi một đối tượng python được tuần tự hóa từ jython và sau đó gọi một số hàm thay đổi dữ liệu trong các thành viên của nó, thì bạn sẽ không thấy những thay đổi đó trong java. Bạn chỉ cần nhớ gửi lại dữ liệu mà bạn muốn từ pyro. Tôi tin rằng đây là cách dễ nhất để đạt được cpython! Bạn không cần bất kỳ jni hoặc jna hoặc swig hoặc .... Bạn không cần biết bất kỳ c, hoặc c ++ nào. kool hả?

Ưu điểm: Truy cập cpython, không khó như các phương pháp sau

Nhược điểm: Không thể thay đổi dữ liệu thành viên của các đối tượng java trực tiếp từ python. Có phần gián tiếp, (jython là người đàn ông trung gian).

Java sang C / C ++ qua JNI / JNA / SWIG sang Python thông qua trình thông dịch nhúng (có thể sử dụng Thư viện BOOST?)

OMG phương pháp này không dành cho những người yếu tim. Và tôi có thể nói với bạn rằng tôi đã mất rất nhiều thời gian để đạt được điều này với một phương pháp tốt. Lý do chính mà bạn muốn làm điều này là để bạn có thể chạy mã cpython được kiểm soát hoàn toàn trên đối tượng java của bạn. Có những điều chính cần cân nhắc trước khi quyết định thử ăn bánh mì java (giống tinh tinh) với python (giống ngựa). Thứ nhất nếu bạn gặp sự cố trình thông dịch sẽ tắt cho chương trình của bạn! Và đừng khiến tôi bắt đầu về các vấn đề đồng thời! Ngoài ra, có allot allot của nồi hơi, tôi tin rằng tôi đã tìm thấy cấu hình tốt nhất để giảm thiểu nồi hơi này nhưng nó vẫn là allot! Vì vậy, làm thế nào để tiếp tục điều này: Hãy xem xét rằng C ++ là trung gian của bạn, các đối tượng của bạn thực sự là các đối tượng c ++! Thật tốt khi bạn biết điều đó ngay bây giờ. Chỉ cần viết đối tượng của bạn như thể chương trình của bạn như trong cpp không phải java, với dữ liệu bạn muốn truy cập từ cả hai thế giới. Sau đó, bạn có thể sử dụng trình tạo trình bao bọc được gọi là swig (http://www.swig.org/Doc1.3/Java.html ) để làm cho nó có thể truy cập được vào java và biên dịch một dll mà bạn gọi là System.load (tên dll ở đây) trong java. Hãy làm việc này trước, sau đó chuyển sang phần khó! Để truy cập python, bạn cần phải nhúng một trình thông dịch. Trước hết tôi khuyên bạn nên thực hiện một số chương trình thông dịch viên chào hay hướng dẫn này Nhúng python trong C / C . Một khi bạn đã làm việc đó, đã đến lúc làm cho con ngựa và con khỉ nhảy múa! Bạn có thể gửi đối tượng c ++ cho python qua [boost] [3]. Tôi biết tôi đã không đưa cho bạn con cá, chỉ nói cho bạn biết nơi để tìm con cá. Một số gợi ý cần lưu ý khi biên dịch.

Khi bạn biên dịch boost, bạn sẽ cần phải biên dịch một thư viện được chia sẻ. Và bạn cần phải bao gồm và liên kết đến những thứ bạn cần từ jdk, tức là functionst.lib, jvm.lib, (bạn cũng sẽ cần client jvm.dll trong đường dẫn của mình khi khởi chạy ứng dụng) Cũng như python27.lib hoặc bất cứ thứ gì và boost_python-vc100-mt-1_55.lib. Sau đó, bao gồm Python / include, jdk / include, boost và chỉ sử dụng các thư viện được chia sẻ (dlls), nếu không thì boost sẽ bị chảy nước mắt. Và tôi biết. Có rất nhiều cách mà điều này có thể trở nên chua chát. Vì vậy, hãy đảm bảo rằng bạn hoàn thành từng việc từng khối một. Sau đó ghép chúng lại với nhau.


2
Đây là một thư viện cho phép bạn viết các tập lệnh python của mình một lần và quyết định phương pháp tích hợp nào (Jython, CPython qua Jep và Py4j) để sử dụng trong thời gian chạy: github.com/subes/invesdwin-context-python Vì mỗi phương pháp có lợi ích / nhược điểm riêng
subes

@subes rằng dự án trông tuyệt vời. Tôi đã viết bài này một lúc trước. Tôi khuyến khích bạn viết một câu trả lời mà tôi sẽ tán thành nó. Tôi không thích câu trả lời hàng đầu haha ​​vì tôi không nghĩ nó cung cấp nhiều thông tin hữu ích ngoài tìm kiếm trên google.
Snickers3192

Tôi đã tạo một câu trả lời riêng
subes

3
câu trả lời này có mùi "đây phải là câu trả lời được chấp nhận" hay chỉ là tôi? ;-)
Mauricio Gracia Gutierrez

18

Thật không thông minh khi có mã python bên trong java. Bọc mã python của bạn bằng flask hoặc khuôn khổ web khác để biến nó thành một microservice. Làm cho chương trình java của bạn có thể gọi microservice này (ví dụ: qua REST).

Thông báo cho tôi, điều này rất đơn giản và sẽ giúp bạn tiết kiệm rất nhiều vấn đề. Và các mã được ghép nối lỏng lẻo để chúng có thể mở rộng.

Cập nhật vào ngày 24 tháng 3 năm 2020: Theo nhận xét của @ stx, cách tiếp cận trên không phù hợp để truyền dữ liệu lớn giữa máy khách và máy chủ. Đây là một cách tiếp cận khác mà tôi đề xuất: Kết nối Python và Java với Rust (C / C ++ cũng ok). https://medium.com/@shmulikamar/https-medium-com-shmulikamar-connecting-python-and-java-with-rust-11c256a1dfb0


+1, nhưng còn hiệu suất bổ sung và chi phí giao tiếp khi tạo và phân tích cú pháp thư qua lại ở cả hai đầu thì sao?
stx

có, điều này cần xác định một giao diện api với yêu cầu đầu vào / đầu ra tối thiểu. Sẽ không thông minh nếu có nhiều bộ chuyển đổi dữ liệu giữa máy khách / máy chủ trên mạng. Nếu bạn không thể xác định một giao diện như vậy, thì cách tiếp cận thiết kế này không phù hợp.
Peiming Hu

10

Một số câu trả lời đề cập rằng bạn có thể sử dụng JNI hoặc JNA để truy cập cpython nhưng tôi không khuyên bạn nên bắt đầu từ đầu vì đã có các thư viện mã nguồn mở để truy cập cpython từ java. Ví dụ:


8

Đây là một thư viện cho phép bạn viết các tập lệnh python của mình một lần và quyết định phương pháp tích hợp nào (Jython, CPython / PyPy qua Jep và Py4j) để sử dụng trong thời gian chạy:

https://github.com/subes/invesdwin-context-python

Vì mỗi phương pháp có những lợi ích / nhược điểm riêng như được giải thích trong liên kết.


Dự án này không có bất kỳ bản phát hành nào.
Christian Schlichtherle

@ChristianSchlichtherle Investdwin-context-python phiên bản 1.0.0 không khả dụng; nhờ đá quý này chút: github.com/loewenfels/dep-graph-releaser
subes

6

Nó phụ thuộc vào những gì bạn có nghĩa là các chức năng python? nếu chúng được viết bằng cpython, bạn không thể gọi trực tiếp chúng, bạn sẽ phải sử dụng JNI , nhưng nếu chúng được viết bằng Jython, bạn có thể dễ dàng gọi chúng từ java, vì jython cuối cùng tạo ra mã byte java.

Bây giờ khi tôi nói được viết bằng cpython hoặc jython, nó không có ý nghĩa gì nhiều vì python là python và hầu hết mã sẽ chạy trên cả hai triển khai trừ khi bạn đang sử dụng các thư viện cụ thể dựa trên cpython hoặc java.

xem tại đây cách sử dụng trình thông dịch Python trong Java.


5

Tùy thuộc vào yêu cầu của bạn, các tùy chọn như XML-RPC có thể hữu ích, có thể được sử dụng để gọi các hàm từ xa hầu như bằng bất kỳ ngôn ngữ nào hỗ trợ giao thức.


5

GraalVM là một lựa chọn tốt. Tôi đã thực hiện kết hợp Java + Javascript với GraalVM cho thiết kế microservice (Java với phản chiếu Javascript). Gần đây, họ đã thêm hỗ trợ cho python, tôi đặc biệt muốn thử với cộng đồng của nó đã trở nên lớn mạnh như thế nào trong những năm qua.


4

Bạn có thể gọi bất kỳ ngôn ngữ nào từ java bằng Java Native Interface


6
Bất kỳ ngôn ngữ nào mà chính nó có thể được gọi từ c đó là. Cũng được, python có thể, nhưng Jython thực sự là một giải pháp đơn giản hơn nhiều (hoặc sử dụng PyInterpreter trong j6 +). Việc viết mã để gọi các hàm python từ c không phải là chuyện nhỏ.
Voo

2

Jython có một số hạn chế:

Có một số khác biệt. Đầu tiên, các chương trình Jython không thể sử dụng các mô-đun mở rộng CPython được viết bằng C. Các mô-đun này thường có các tệp có phần mở rộng .so, .pyd hoặc .dll. Nếu bạn muốn sử dụng một mô-đun như vậy, bạn nên tìm một mô-đun tương đương được viết bằng Python hoặc Java thuần túy. Mặc dù về mặt kỹ thuật, việc hỗ trợ các phần mở rộng như vậy là khả thi - IronPython làm như vậy - không có kế hoạch làm như vậy trong Jython.

Phân phối các tập lệnh Python của tôi dưới dạng tệp JAR với Jython?

bạn có thể chỉ cần gọi các tập lệnh python (hoặc tập lệnh bash hoặc Perl) từ Java bằng cách sử dụng Runtime hoặc ProcessBuilder và chuyển đầu ra trở lại Java:

Chạy một tập lệnh bash shell trong java

Chạy dòng lệnh trong Java

java runtime.getruntime () nhận đầu ra từ việc thực hiện một chương trình dòng lệnh


0

Điều này cung cấp một cái nhìn tổng quan khá tốt về các tùy chọn hiện tại. Một số trong số đó được đặt tên trong các câu trả lời khác. Jython không thể sử dụng được cho đến khi họ quyết định triển khai Python 3.x và nhiều dự án khác đang hình thành phía python và muốn truy cập java. Nhưng vẫn còn một số tùy chọn, để đặt tên cho một cái gì đó chưa được đặt tên: gRPC

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.