Chamando Python em Java?


Respostas:


100

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

Instalei o JYthon, ou presumo que instalei, e continuo tentando executar o código que você descreveu, mas ele destacou como um erro. A instalação do Jython precisa ir para uma pasta específica, nas pastas python ou java?
Shahab

2
Não há nenhum erro, estou apenas tendo dificuldade em integrar Jython ao Netbeans
Shahab

Se não houvesse erro, funcionaria, então obviamente não é o caso;) "Erro" não significa erro de tempo de execução, poderia ser um erro de compilação também.
Voo

Que pena, era um uso indevido da palavra. Eu estava tentando adicionar o jython.jar ao meu projeto e ao netbeans. Eu descobri
Shahab

1
O fim da vida útil do Python 2 é 1.1.2020 e o Jython suporta apenas o Python 2.7. então nenhum Jython está basicamente morto. A melhor (mais simples) opção é Jep lib
garyee

62

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.


2
Aqui está uma biblioteca que permite escrever seus scripts Python uma vez e decidir qual método de integração (Jython, CPython via Jep e Py4j) usar em tempo de execução: github.com/subes/invesdwin-context-python Visto que cada método tem seus próprios benefícios / desvantagens
subes

@subes esse projeto parece incrível. Eu escrevi isso há um tempo. Eu o encorajo a escrever uma resposta que eu votaria positivamente. Não gosto da resposta principal haha ​​porque não acho que ela forneça muitas informações úteis fora de uma pesquisa no Google.
Snickers3192

Eu criei uma resposta separada
subes

3
essa resposta cheira a "esta deve ser a resposta aceita" ou é só eu? ;-)
Mauricio Gracia Gutierrez

18

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


+1, mas e quanto ao desempenho adicional e sobrecarga de comunicação de criar e analisar mensagens de um lado para outro em ambas as extremidades?
stx

sim, isso precisa definir uma interface api com entrada / saída mínima necessária. Não é inteligente ter uma grande quantidade de transferência de dados entre cliente / servidor na rede. Se você não pode definir essa interface, essa abordagem de design não é adequada.
Peiming Hu

10

Várias das respostas mencionam que você pode usar JNI ou JNA para acessar cpython, mas eu não recomendaria começar do zero porque já existem bibliotecas de código aberto para acessar cpython de java. Por exemplo:


8

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.


Este projeto não tem nenhum lançamento.
Christian Schlichtherle

@ChristianSchlichtherle invesdwin-context-python versão 1.0.0 não está disponível; graças a esta pequena joia: github.com/loewenfels/dep-graph-releaser
subes

6

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.

veja aqui como usar o interpretador Python em Java.


5

Dependendo de seus requisitos, opções como XML-RPC podem ser úteis, que podem ser usadas para chamar funções remotamente virtualmente em qualquer linguagem que suporte o protocolo.


5

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.


4

Você pode chamar qualquer linguagem de java usando Java Native Interface


6
Qualquer linguagem que possa ser chamada a partir de c. Bem, ok python pode, mas Jython é uma solução muito mais simples lá (ou usando o PyInterpreter em j6 +). Não é tão trivial escrever o código para chamar funções python de c.
Voo

2

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


0

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.