เรียก Python ใน Java?


117

ฉันสงสัยว่าเป็นไปได้หรือไม่ที่จะเรียกฟังก์ชัน python จากรหัส java โดยใช้ jython หรือเรียกรหัส java จาก python เท่านั้น


3
โปรดดูคำถามที่คล้ายกันและอ่านคำตอบ bytes.com/topic/python/answers/…
AlexR

คำตอบ:


101

Jython: Python สำหรับแพลตฟอร์ม Java - http://www.jython.org/index.html

คุณสามารถเรียกใช้ฟังก์ชัน python จากโค้ด Java ด้วย Jython ได้อย่างง่ายดาย นั่นคือตราบเท่าที่โค้ด python ของคุณทำงานภายใต้ jython นั่นคือไม่ใช้ c-extensions บางตัวที่ไม่รองรับ

หากวิธีนี้เหมาะกับคุณแน่นอนว่าเป็นวิธีที่ง่ายที่สุดที่คุณจะได้ มิฉะนั้นคุณสามารถใช้org.python.util.PythonInterpreterจากการสนับสนุนล่าม Java6 ใหม่

ตัวอย่างง่ายๆจากด้านบนของหัวของฉัน - แต่ฉันหวังว่าจะได้ผล: (ไม่มีการตรวจสอบข้อผิดพลาดสำหรับความกะทัดรัด)

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);

ฉันได้ติดตั้ง JYthon แล้วหรือฉันคิดว่าฉันทำไปแล้วและฉันพยายามเรียกใช้โค้ดที่คุณระบุไว้ แต่มันถูกเน้นว่าเป็นข้อผิดพลาด การติดตั้ง Jython จำเป็นต้องไปที่โฟลเดอร์ใดโฟลเดอร์หนึ่งทั้งในโฟลเดอร์ python หรือ java หรือไม่
Shahab

2
ไม่มีข้อผิดพลาดใด ๆ ฉันเพิ่งประสบปัญหาในการรวม Jython เข้ากับ Netbeans
Shahab

หากไม่มีข้อผิดพลาดก็จะใช้งานได้ดังนั้นจึงไม่ชัดเจนในกรณีนี้) "ข้อผิดพลาด" ไม่ได้หมายถึงข้อผิดพลาดรันไทม์อาจเป็นข้อผิดพลาดในการคอมไพล์เช่นกัน
Voo

ไม่ดีของฉันมันเป็นการใช้คำที่ไม่ดี ฉันพยายามเพิ่ม jython.jar ในโปรเจ็กต์และ netbeans ของฉัน ฉันคิดออกแล้ว
ฮับ

1
Python 2 end of Life คือ 1.1.2020 และ Jython รองรับ Python 2.7 เท่านั้น ดังนั้นจึงไม่มี Jython ที่ตายโดยทั่วไป ตัวเลือกที่ดีที่สุด (ง่ายที่สุด) คือ Jep lib
garyee

63

เฮ้ฉันคิดว่าฉันจะตอบคำถามนี้แม้ว่ามันจะสายไปแล้วก็ตาม ฉันคิดว่ามีสิ่งสำคัญที่ต้องพิจารณาก่อนว่าคุณต้องการให้การเชื่อมโยงระหว่าง java และ python มีความรัดกุมเพียงใด

ประการแรก คุณต้องการเรียกใช้ฟังก์ชันเท่านั้นหรือคุณต้องการให้รหัส python เปลี่ยนข้อมูลในวัตถุ java ของคุณหรือไม่? สิ่งนี้สำคัญมาก หากคุณต้องการเรียกโค้ด python เพียงบางส่วนโดยมีหรือไม่มีอาร์กิวเมนต์นั่นก็ไม่ใช่เรื่องยาก หากอาร์กิวเมนต์ของคุณเป็นแบบดั้งเดิมมันจะทำให้ง่ายยิ่งขึ้น อย่างไรก็ตามหากคุณต้องการให้คลาส java ใช้ฟังก์ชันสมาชิกใน python ซึ่งเปลี่ยนข้อมูลของวัตถุ java นี่ไม่ใช่เรื่องง่ายหรือตรงไปตรงมา

ประการที่สองเรากำลังพูดถึง cpython หรือ jython จะทำอย่างไร ฉันจะบอกว่า cpython อยู่ที่ไหน! ฉันจะสนับสนุนนี่คือสาเหตุที่ python เป็นคนคูล! มีนามธรรมสูงเช่นนี้อย่างไรก็ตามสามารถเข้าถึง c, c ++ ได้เมื่อจำเป็น ลองนึกภาพว่าคุณมีสิ่งนั้นใน java หรือไม่ คำถามนี้ไม่คุ้มค่าที่จะถามว่า jython ใช้ได้หรือไม่เพราะมันง่ายอยู่แล้ว

ดังนั้นฉันจึงเล่นด้วยวิธีการต่อไปนี้และแสดงรายการจากง่ายไปยาก:

Java เป็น Jython

ข้อดี:ง่ายเล็กน้อย มีการอ้างอิงจริงไปยังวัตถุ java

ข้อเสีย:ไม่มี CPython ช้ามาก!

Jython จาก java นั้นง่ายมากและถ้าสิ่งนี้เพียงพอแล้วก็ยอดเยี่ยม อย่างไรก็ตามมันช้ามากและไม่มี cpython! ชีวิตคุ้มไหมถ้าไม่มี cpython ฉันไม่คิดอย่างนั้น! คุณสามารถมีโค้ด python ที่ใช้ฟังก์ชันสมาชิกของคุณสำหรับวัตถุ java ของคุณได้อย่างง่ายดาย

Java เป็น Jython เป็น CPython ผ่าน Pyro

Pyro เป็นโมดูลวัตถุระยะไกลสำหรับ python คุณมีอ็อบเจ็กต์บางอย่างบนตัวแปล cpython และคุณสามารถส่งอ็อบเจ็กต์ที่ถ่ายโอนผ่านการทำให้เป็นอนุกรมและยังสามารถส่งคืนอ็อบเจ็กต์ด้วยวิธีนี้ โปรดทราบว่าหากคุณส่งอ็อบเจกต์ python แบบอนุกรมจาก jython แล้วเรียกใช้ฟังก์ชันบางอย่างที่เปลี่ยนแปลงข้อมูลในสมาชิกคุณจะไม่เห็นการเปลี่ยนแปลงเหล่านั้นใน java คุณต้องจำไว้ว่าให้ส่งข้อมูลที่คุณต้องการกลับมาจากไพโร ฉันเชื่อว่าเป็นวิธีที่ง่ายที่สุดในการเข้าถึง cpython! คุณไม่จำเป็นต้องมี jni หรือ jna หรือ swig หรือ .... คุณไม่จำเป็นต้องรู้ c หรือ c ++ ใด ๆ คูลเหรอ?

ข้อดี:เข้าถึง cpython ไม่ยากเหมือนวิธีการต่อไปนี้

ข้อเสีย:ไม่สามารถเปลี่ยนข้อมูลสมาชิกของวัตถุ java จาก python ได้โดยตรง ค่อนข้างทางอ้อม (jython คือคนกลาง)

Java เป็น C / C ++ ผ่าน JNI / JNA / SWIG ไปยัง Python ผ่าน Embedded interpreter (อาจใช้ BOOST Libraries?)

OMG วิธีนี้ไม่เหมาะสำหรับคนใจร้อน และฉันสามารถบอกคุณได้ว่าฉันใช้เวลานานมากในการบรรลุเป้าหมายนี้ด้วยวิธีการที่เหมาะสม เหตุผลหลักที่คุณต้องการทำเช่นนี้คือเพื่อให้คุณสามารถเรียกใช้โค้ด cpython ซึ่งเป็นบังเหียนทั้งหมดเหนือวัตถุ java ของคุณ มีสิ่งสำคัญที่ควรพิจารณาก่อนตัดสินใจลองและ bread java (ซึ่งเหมือนลิงชิมแปนซี) กับ python (ซึ่งเหมือนม้า) ประการแรกถ้าคุณขัดข้องล่ามที่จะทำให้คุณโปรแกรม! และอย่าให้ฉันเริ่มปัญหาการเกิดพร้อมกัน! นอกจากนี้ยังมีการจัดสรรหม้อไอน้ำอีกมากมายฉันเชื่อว่าฉันได้พบการกำหนดค่าที่ดีที่สุดในการลดหม้อไอน้ำนี้ แต่ก็ยังคงเป็นการจัดสรร! แล้วจะไปเกี่ยวกับสิ่งนี้ได้อย่างไร: พิจารณาว่า C ++ เป็นคนกลางของคุณวัตถุของคุณเป็นวัตถุ c ++ จริงๆ! ดีที่คุณรู้ว่าตอนนี้ เพียงแค่เขียนวัตถุของคุณราวกับว่าโปรแกรมของคุณใน cpp ไม่ใช่ java ด้วยข้อมูลที่คุณต้องการเข้าถึงจากทั้งสองโลก จากนั้นคุณสามารถใช้เครื่องกำเนิดไฟฟ้าที่เรียกว่า swig (http://www.swig.org/Doc1.3/Java.html ) เพื่อให้สามารถเข้าถึง java และรวบรวม dll ที่คุณเรียกว่า System.load (ชื่อ dll ที่นี่) ใน java ทำงานนี้ก่อนจากนั้นไปยังส่วนที่ยาก! ในการเข้าถึง python คุณต้องฝังล่าม ประการแรกผมขอแนะนำให้ทำบางโปรแกรมล่ามสวัสดีหรือการกวดวิชานี้ฝังหลามใน C / C เมื่อคุณทำงานได้แล้วก็ถึงเวลาที่จะทำให้ม้าและลิงเต้นรำ! คุณสามารถส่งวัตถุ c ++ ไปยัง python ผ่าน [boost] [3] ฉันรู้ว่าฉันไม่ได้ให้ปลาคุณเพียง แต่บอกคุณว่าจะหาปลาได้ที่ไหน คำแนะนำบางประการที่ควรทราบสำหรับสิ่งนี้เมื่อรวบรวม

เมื่อคุณคอมไพล์บูสต์คุณจะต้องคอมไพล์ไลบรารีที่ใช้ร่วมกัน และคุณต้องรวมและเชื่อมโยงไปยังสิ่งที่คุณต้องการจาก jdk เช่น jawt.lib, jvm.lib (คุณจะต้องมีไคลเอนต์ jvm.dll ในเส้นทางของคุณเมื่อเปิดแอปพลิเคชัน) เช่นเดียวกับ python27.lib หรือ อะไรก็ตามและ boost_python-vc100-mt-1_55.lib จากนั้นรวม Python / include, jdk / include, boost และใช้เฉพาะไลบรารีที่ใช้ร่วมกัน (dlls) มิฉะนั้นการเพิ่มจะมีปัญหา และอิ่มกับฉันรู้ มีหลายวิธีที่สามารถทำให้เปรี้ยวได้ ดังนั้นให้แน่ใจว่าคุณทำแต่ละอย่างเสร็จทีละบล็อก จากนั้นนำมารวมกัน


2
นี่คือไลบรารีที่ให้คุณเขียนสคริปต์ python ของคุณเพียงครั้งเดียวและตัดสินใจว่าจะใช้วิธีการรวม (Jython, CPython ผ่าน Jep และ Py4j) ที่รันไทม์: github.com/subes/invesdwin-context-pythonเนื่องจากแต่ละวิธีมีประโยชน์ / ข้อเสียของตัวเอง
ย่อย

@subes โปรเจ็กต์นั้นดูดีมากฉันเขียนเมื่อสักครู่ที่ผ่านมา ฉันขอแนะนำให้คุณเขียนคำตอบที่ฉันอยากจะโหวตให้ ฉันไม่ชอบคำตอบอันดับต้น ๆ ฮ่า ๆ เพราะฉันไม่คิดว่ามันให้ข้อมูลที่เป็นประโยชน์มากนักนอกการค้นหาของ Google
Snickers3192

ฉันสร้างคำตอบแยกต่างหาก
ย่อย

3
คำตอบนี้มีกลิ่นที่ "ควรเป็นคำตอบที่ยอมรับ" หรือเป็นเพียงฉัน? ;-)
Mauricio Gracia Gutierrez

18

ไม่ฉลาดที่จะมีรหัส python ใน java ห่อรหัส python ของคุณด้วย flask หรือเว็บเฟรมเวิร์กอื่น ๆ เพื่อทำเป็นไมโครเซอร์วิส ทำให้โปรแกรม java ของคุณสามารถเรียกใช้ไมโครเซอร์วิสนี้ได้ (เช่นผ่าน REST)

โปรดฟังฉันนี่เป็นเรื่องง่ายมากและจะช่วยคุณประหยัดปัญหาได้มากมาย และรหัสจะเชื่อมโยงกันอย่างหลวม ๆ เพื่อให้สามารถปรับขนาดได้

อัปเดตเมื่อวันที่ 24 มีนาคม 2020: ตามความคิดเห็นของ @ stx วิธีการข้างต้นไม่เหมาะสำหรับการถ่ายโอนข้อมูลจำนวนมากระหว่างไคลเอนต์และเซิร์ฟเวอร์ นี่เป็นอีกแนวทางหนึ่งที่ฉันแนะนำ: การเชื่อมต่อ Python และ Java กับ Rust (C / C ++ ก็โอเค) https://medium.com/@shmulikamar/https-medium-com-shmulikamar-connecting-python-and-java-with-rust-11c256a1dfb0


+1 แต่สิ่งที่เกี่ยวกับประสิทธิภาพเพิ่มเติมและค่าใช้จ่ายในการสื่อสารในการสร้างและแยกวิเคราะห์ข้อความไปมาทั้งสองด้านล่ะ?
stx

ใช่สิ่งนี้จำเป็นต้องกำหนดอินเตอร์เฟส api ด้วยอินพุต / เอาต์พุตขั้นต่ำที่ต้องการ ไม่ใช่เรื่องฉลาดที่จะมีการส่งต่อข้อมูลจำนวนมากระหว่างไคลเอนต์ / เซิร์ฟเวอร์บนเครือข่าย หากคุณไม่สามารถกำหนดอินเทอร์เฟซดังกล่าวได้แสดงว่าแนวทางการออกแบบนี้ไม่เหมาะสม
Peiming Hu

10

คำตอบหลายคำกล่าวว่าคุณสามารถใช้ JNI หรือ JNA เพื่อเข้าถึง cpython ได้ แต่ฉันไม่แนะนำให้เริ่มตั้งแต่ต้นเพราะมีไลบรารีโอเพนซอร์สสำหรับการเข้าถึง cpython จาก java อยู่แล้ว ตัวอย่างเช่น:


8

นี่คือไลบรารีที่ให้คุณเขียนสคริปต์ python ของคุณเพียงครั้งเดียวและตัดสินใจว่าจะใช้วิธีการรวม (Jython, CPython / PyPy ผ่าน Jep และ Py4j) ที่รันไทม์:

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

เนื่องจากแต่ละวิธีมีประโยชน์ / ข้อเสียของตัวเองตามที่อธิบายไว้ในลิงค์


โครงการนี้ไม่มีการเปิดตัวใด ๆ
Christian Schlichtherle

@ChristianSchlichtherle invesdwin-context-python เวอร์ชัน 1.0.0 ไม่พร้อมใช้งาน ขอบคุณอัญมณีเล็ก ๆ ชิ้นนี้: github.com/loewenfels/dep-graph-releaser
ย่อย

6

มันขึ้นอยู่กับว่าคุณหมายถึงอะไรโดยฟังก์ชัน python? หากพวกเขาเขียนด้วยcpythonคุณไม่สามารถเรียกมันได้โดยตรงคุณจะต้องใช้JNIแต่ถ้าพวกเขาเขียนด้วยJythonคุณสามารถเรียกมันจาก java ได้อย่างง่ายดายเนื่องจาก jython สร้างโค้ด java byte ในที่สุด

ตอนนี้เมื่อฉันพูดว่าเขียนด้วย cpython หรือ jython มันไม่สมเหตุสมผลเท่าไหร่เพราะ python เป็น python และโค้ดส่วนใหญ่จะทำงานบนการใช้งานทั้งสองอย่างเว้นแต่คุณจะใช้ไลบรารีเฉพาะที่อาศัย cpython หรือ java

ดูวิธีใช้ Python interpreter ใน Java ได้ที่นี่


5

ขึ้นอยู่กับความต้องการของคุณตัวเลือกเช่นXML-RPCอาจมีประโยชน์ซึ่งสามารถใช้เพื่อเรียกฟังก์ชันจากระยะไกลในภาษาใดก็ได้ที่รองรับโปรโตคอล


5

GraalVMเป็นทางเลือกที่ดี ฉันได้ทำการรวม Java + Javascript กับ GraalVM สำหรับการออกแบบ microservice (Java พร้อมการสะท้อนของ Javascript) เมื่อเร็ว ๆ นี้พวกเขาได้เพิ่มการสนับสนุน python ฉันจะลองใช้โดยเฉพาะอย่างยิ่งกับความใหญ่โตของชุมชนในช่วงหลายปีที่ผ่านมา


4

คุณสามารถเรียกภาษาใดก็ได้จาก java โดยใช้Java Native Interface


6
ภาษาใด ๆ ที่สามารถเรียกตัวเองจาก c นั่นคือ โอเค python ทำได้ แต่ Jython เป็นวิธีแก้ปัญหาที่ง่ายกว่ามากจริงๆ (หรือใช้ PyInterpreter ใน j6 +) ไม่ใช่เรื่องเล็กน้อยที่จะเขียนโค้ดเพื่อเรียกใช้ฟังก์ชัน python จาก c
Voo

2

Jython มีข้อ จำกัด บางประการ:

มีจำนวนความแตกต่าง ประการแรกโปรแกรม Jython ไม่สามารถใช้โมดูลส่วนขยาย CPython ที่เขียนด้วย C โมดูลเหล่านี้มักจะมีไฟล์ที่มีนามสกุล. so, .pyd หรือ. dll หากคุณต้องการใช้โมดูลดังกล่าวคุณควรมองหาสิ่งที่เทียบเท่าที่เขียนด้วย Python หรือ Java ล้วน ๆ แม้ว่าในทางเทคนิคจะเป็นไปได้ที่จะรองรับส่วนขยายดังกล่าว แต่ IronPython ก็ทำเช่นนั้น แต่ก็ไม่มีแผนที่จะทำเช่นนั้นใน Jython

แจกจ่ายสคริปต์ Python ของฉันเป็นไฟล์ JAR ด้วย Jython หรือไม่

คุณสามารถเรียกสคริปต์ python (หรือ bash หรือ Perl scripts) จาก Java โดยใช้ Runtime หรือ ProcessBuilder และส่งเอาต์พุตกลับไปยัง Java:

การรัน bash shell script ใน java

รัน Command Line ใน Java

java runtime.getruntime () รับเอาต์พุตจากการรันโปรแกรมบรรทัดคำสั่ง


0

สิ่งนี้ให้ภาพรวมที่ค่อนข้างดีในตัวเลือกปัจจุบัน บางส่วนมีชื่ออยู่ในคำตอบอื่น ๆ Jython ไม่สามารถใช้งานได้จนกว่าพวกเขาจะตัดสินใจใช้ Python 3.x และโปรเจ็กต์อื่น ๆ อีกมากมายกำลังมาจากฝั่ง python และต้องการเข้าถึง java แต่ยังมีตัวเลือกบางอย่างเพื่อตั้งชื่อสิ่งที่ยังไม่ได้ตั้งชื่อ: gRPC

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.