Respostas:
Jython: Python para a plataforma Java - http://www.jython.org/index.html
Você pode facilmente chamar funções python a partir do código Java com Jython. Contanto que seu próprio código python rode em jython, ou seja, não use algumas extensões C que não são suportadas.
Se isso funcionar para você, certamente é a solução mais simples que você pode obter. Caso contrário, você pode usar org.python.util.PythonInterpreter
do novo suporte do interpretador Java6.
Um exemplo simples do topo da minha cabeça - mas deve funcionar, espero: (nenhuma verificação de erro feita por brevidade)
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);
Ei, pensei em responder a isso, embora seja tarde. Eu acho que há algumas coisas importantes a considerar primeiro com o quão forte você deseja ter a ligação entre java e python.
Em primeiro lugar, você deseja apenas chamar funções ou realmente deseja que o código Python altere os dados em seus objetos Java? Isto é muito importante. Se você deseja apenas chamar algum código python com ou sem argumentos, isso não é muito difícil. Se seus argumentos forem primitivos, isso torna tudo ainda mais fácil. No entanto, se você quiser que a classe java implemente funções de membro em python, que alteram os dados do objeto java, isso não é tão fácil ou direto.
Em segundo lugar, estamos falando de cpython ou jython servirá? Eu diria que cpython é onde está! Eu diria que é por isso que o python é tão legal! Ter tais abstrações altas, no entanto, acesse c, c ++ quando necessário. Imagine se você pudesse ter isso em java. Esta questão nem vale a pena perguntar se jython está ok, porque então é fácil de qualquer maneira.
Portanto, usei os seguintes métodos e listei-os de fáceis a difíceis:
Java para Jython
Vantagens: Trivialmente fácil. Ter referências reais a objetos java
Desvantagens: Sem CPython, extremamente lento!
Jython de java é tão fácil, e se isso for realmente suficiente, ótimo. No entanto, é muito lento e sem cpython! Vale a pena viver sem cpython? Acho que não! Você pode facilmente ter código python implementando suas funções de membro para seus objetos java.
Java para Jython para CPython via Pyro
Pyro é o módulo de objeto remoto para python. Você tem algum objeto em um interpretador cpython e pode enviar objetos que são transferidos por serialização e também pode retornar objetos por meio deste método. Observe que se você enviar um objeto Python serializado de jython e, em seguida, chamar algumas funções que alteram os dados em seus membros, você não verá essas alterações em java. Você só precisa se lembrar de enviar de volta os dados que deseja do Pyro. Acredito que essa seja a maneira mais fácil de chegar ao cpython! Você não precisa de nenhum jni ou jna ou gole ou .... Você não precisa conhecer nenhum c ou c ++. kool hein?
Vantagens: Acesso ao cpython, não tão difícil quanto os métodos a seguir
Desvantagens: não é possível alterar os dados de membro de objetos java diretamente do python. É um tanto indireto, (jython é um homem médio).
Java para C / C ++ via JNI / JNA / SWIG para Python via interpretador incorporado (talvez usando bibliotecas BOOST?)
Meu Deus, este método não é para os fracos de coração. E posso dizer que demorei muito para conseguir isso com um método decente. O principal motivo pelo qual você deseja fazer isso é para que possa executar o código cpython, que tem controle total sobre seu objeto java. Há coisas importantes a se considerar antes de decidir experimentar e preparar um pão de java (que é como um chimpanzé) com python (que é como um cavalo). Em primeiro lugar, se você travar o intérprete, isso apaga o seu programa! E não me fale sobre os problemas de simultaneidade! Além disso, há loteamento de caldeira, acredito ter encontrado a melhor configuração para minimizar esta caldeira, mas ainda assim é lotado! Então, como fazer isso: Considere que C ++ é o seu intermediário, seus objetos são na verdade objetos C ++! Que bom que você sabe disso agora. Basta escrever o seu objeto como se o seu programa estivesse em cpp e não em java, com os dados que você deseja acessar de ambos os mundos. Então você pode usar o gerador de wrapper chamado swig (http://www.swig.org/Doc1.3/Java.html ) para tornar isso acessível para java e compilar uma dll que você chama System.load (nome da dll aqui) em java. Faça isso funcionar primeiro, depois vá para a parte mais difícil! Para chegar ao python, você precisa incorporar um interpretador. Em primeiro lugar eu sugiro fazer alguns programas de intérprete olá ou este tutorial Embedding python em C / C . Depois de fazer isso funcionar, é hora de fazer o cavalo e o macaco dançarem! Você pode enviar um objeto c ++ para python via [boost] [3]. Sei que não lhe dei o peixe, apenas disse onde encontrá-lo. Algumas dicas a serem observadas durante a compilação.
Ao compilar o boost, você precisará compilar uma biblioteca compartilhada. E você precisa incluir e vincular as coisas que você precisa do jdk, ou seja, jawt.lib, jvm.lib, (você também precisará do cliente jvm.dll em seu caminho ao iniciar o aplicativo), bem como o python27.lib ou seja o que for e o boost_python-vc100-mt-1_55.lib. Em seguida, inclua Python / include, jdk / include, boost e use apenas bibliotecas compartilhadas (dlls), caso contrário, o boost tem um rasgo. E sim completo, eu sei. Existem muitas maneiras pelas quais isso pode azedar. Portanto, certifique-se de fazer cada coisa bloco a bloco. Em seguida, coloque-os juntos.
Não é inteligente ter código python dentro de java. Envolva seu código Python com flask ou outra estrutura da web para torná-lo um microsserviço. Torne seu programa java capaz de chamar este microsserviço (por exemplo, via REST).
Acredite em mim, isso é muito simples e economizará toneladas de problemas. E os códigos são fracamente acoplados, portanto, são escalonáveis.
Atualizado em 24 de março de 2020: De acordo com o comentário de @stx, a abordagem acima não é adequada para transferência massiva de dados entre cliente e servidor. Aqui está outra abordagem que eu recomendei: Conectando Python e Java com Rust (C / C ++ também está ok). https://medium.com/@shmulikamar/https-medium-com-shmulikamar-connecting-python-and-java-with-rust-11c256a1dfb0
Aqui está uma biblioteca que permite escrever seus scripts Python uma vez e decidir qual método de integração (Jython, CPython / PyPy via Jep e Py4j) usar no tempo de execução:
https://github.com/subes/invesdwin-context-python
Uma vez que cada método tem suas próprias vantagens / desvantagens, conforme explicado no link.
Depende do que você entende por funções python? se eles foram escritos em cpython, você não pode chamá-los diretamente, você terá que usar JNI , mas se eles foram escritos em Jython, você pode chamá-los facilmente de java, já que o jython acaba gerando código de bytes java.
Agora, quando digo escrito em cpython ou jython, não faz muito sentido porque python é python e a maioria do código será executado em ambas as implementações, a menos que você esteja usando bibliotecas específicas que dependem de cpython ou java.
GraalVM é uma boa escolha. Fiz a combinação Java + Javascript com GraalVM para design de microsserviços (Java com reflexão Javascript). Recentemente, eles adicionaram suporte para python, eu daria uma chance, especialmente com o quão grande sua comunidade se tornou ao longo dos anos.
Você pode chamar qualquer linguagem de java usando Java Native Interface
Jython tem algumas limitações:
Existem várias diferenças. Primeiro, os programas Jython não podem usar módulos de extensão CPython escritos em C. Esses módulos geralmente têm arquivos com a extensão .so, .pyd ou .dll. Se você quiser usar esse módulo, deve procurar um equivalente escrito em Python ou Java puro. Embora seja tecnicamente viável oferecer suporte a tais extensões - IronPython o faz - não há planos de fazê-lo em Jython.
Distribuindo meus scripts Python como arquivos JAR com Jython?
você pode simplesmente chamar scripts python (ou scripts bash ou Perl) de Java usando Runtime ou ProcessBuilder e passar a saída de volta para Java:
Executando um script bash shell em java
Executando linha de comando em Java
java runtime.getruntime () obtendo saída da execução de um programa de linha de comando
Isso dá uma boa visão geral das opções atuais. Alguns deles são mencionados em outras respostas. Jython não é utilizável até que decidam implementar Python 3.x e muitos dos outros projetos estão vindo do lado python e desejam acessar java. Mas ainda existem algumas opções, para nomear algo que ainda não foi nomeado: gRPC