ฉันสงสัยว่าเป็นไปได้หรือไม่ที่จะเรียกฟังก์ชัน python จากรหัส java โดยใช้ jython หรือเรียกรหัส java จาก python เท่านั้น
ฉันสงสัยว่าเป็นไปได้หรือไม่ที่จะเรียกฟังก์ชัน python จากรหัส java โดยใช้ jython หรือเรียกรหัส java จาก python เท่านั้น
คำตอบ:
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);
เฮ้ฉันคิดว่าฉันจะตอบคำถามนี้แม้ว่ามันจะสายไปแล้วก็ตาม ฉันคิดว่ามีสิ่งสำคัญที่ต้องพิจารณาก่อนว่าคุณต้องการให้การเชื่อมโยงระหว่าง 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) มิฉะนั้นการเพิ่มจะมีปัญหา และอิ่มกับฉันรู้ มีหลายวิธีที่สามารถทำให้เปรี้ยวได้ ดังนั้นให้แน่ใจว่าคุณทำแต่ละอย่างเสร็จทีละบล็อก จากนั้นนำมารวมกัน
ไม่ฉลาดที่จะมีรหัส 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
คำตอบหลายคำกล่าวว่าคุณสามารถใช้ JNI หรือ JNA เพื่อเข้าถึง cpython ได้ แต่ฉันไม่แนะนำให้เริ่มตั้งแต่ต้นเพราะมีไลบรารีโอเพนซอร์สสำหรับการเข้าถึง cpython จาก java อยู่แล้ว ตัวอย่างเช่น:
นี่คือไลบรารีที่ให้คุณเขียนสคริปต์ python ของคุณเพียงครั้งเดียวและตัดสินใจว่าจะใช้วิธีการรวม (Jython, CPython / PyPy ผ่าน Jep และ Py4j) ที่รันไทม์:
https://github.com/subes/invesdwin-context-python
เนื่องจากแต่ละวิธีมีประโยชน์ / ข้อเสียของตัวเองตามที่อธิบายไว้ในลิงค์
มันขึ้นอยู่กับว่าคุณหมายถึงอะไรโดยฟังก์ชัน python? หากพวกเขาเขียนด้วยcpythonคุณไม่สามารถเรียกมันได้โดยตรงคุณจะต้องใช้JNIแต่ถ้าพวกเขาเขียนด้วยJythonคุณสามารถเรียกมันจาก java ได้อย่างง่ายดายเนื่องจาก jython สร้างโค้ด java byte ในที่สุด
ตอนนี้เมื่อฉันพูดว่าเขียนด้วย cpython หรือ jython มันไม่สมเหตุสมผลเท่าไหร่เพราะ python เป็น python และโค้ดส่วนใหญ่จะทำงานบนการใช้งานทั้งสองอย่างเว้นแต่คุณจะใช้ไลบรารีเฉพาะที่อาศัย cpython หรือ java
ขึ้นอยู่กับความต้องการของคุณตัวเลือกเช่นXML-RPCอาจมีประโยชน์ซึ่งสามารถใช้เพื่อเรียกฟังก์ชันจากระยะไกลในภาษาใดก็ได้ที่รองรับโปรโตคอล
GraalVMเป็นทางเลือกที่ดี ฉันได้ทำการรวม Java + Javascript กับ GraalVM สำหรับการออกแบบ microservice (Java พร้อมการสะท้อนของ Javascript) เมื่อเร็ว ๆ นี้พวกเขาได้เพิ่มการสนับสนุน python ฉันจะลองใช้โดยเฉพาะอย่างยิ่งกับความใหญ่โตของชุมชนในช่วงหลายปีที่ผ่านมา
คุณสามารถเรียกภาษาใดก็ได้จาก java โดยใช้Java Native Interface
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
java runtime.getruntime () รับเอาต์พุตจากการรันโปรแกรมบรรทัดคำสั่ง