Akashic Records

자바에서 파이썬 코드 호출하기 본문

Kotlin for Beginners

자바에서 파이썬 코드 호출하기

Andrew's Akashic Records 2024. 4. 26. 10:24
728x90

위는 파이썬 웹 크롤러 프로그램의 개념적 다이어그램을 나타낸 이미지입니다. 이 이미지는 컴퓨터 화면에 코드가 표시되고, 웹 서버와의 데이터 요청 및 응답을 상징하는 화살표가 흐름을 보여주는 모습을 단순하고 교육적인 스타일로 표현하고 있습니다. 컴퓨터는 'Web Crawler'로, 웹 서버는 'Website'로 레이블이 붙어 있습니다.

 

자바에서 파이썬 코드를 호출하는 것은 몇 가지 방법을 통해 가능합니다. 여기에 가장 흔하게 사용되는 두 가지 방법을 소개하겠습니다.

 

1. Jython 사용하기

Jython은 자바 플랫폼에서 파이썬 코드를 실행할 수 있게 해주는 인터프리터입니다. Jython을 사용하면 자바 프로그램 내에서 직접 파이썬 코드를 실행할 수 있습니다.

 

설치 방법:

  1. Jython 공식 웹사이트에서 Jython Jar 파일을 다운로드합니다.
  2. 자바 프로젝트에 Jython Jar 파일을 추가합니다.

예제 코드:

import org.python.util.PythonInterpreter;

public class JythonExample {
    public static void main(String[] args) {
        PythonInterpreter interpreter = new PythonInterpreter();
        interpreter.exec("print('Hello from Python')");
    }
}

이 예제는 Jython을 사용하여 파이썬 코드를 실행하는 간단한 방법을 보여줍니다.

 

2. ProcessBuilder 사용하기

자바의 ProcessBuilder 클래스를 사용하면 외부 프로그램을 실행할 수 있으며, 이를 통해 파이썬 스크립트를 실행할 수도 있습니다.

 

예제 코드:

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class PythonCallExample {
    public static void main(String[] args) {
        try {
            ProcessBuilder pb = new ProcessBuilder("python", "script.py");
            Process p = pb.start();

            BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                System.out.println(line);
            }
            int exitCode = p.waitFor();
            System.out.println("Python script exited with code " + exitCode);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

이 코드는 script.py라는 파이썬 스크립트 파일을 실행하고 그 결과를 출력합니다. script.py 파일은 자바 프로그램이 실행되는 디렉토리에 위치해야 합니다.

 

두 방법 중 어느 것을 사용할지는 개발 환경, 필요한 라이브러리, 그리고 성능 요구사항 등을 고려하여 결정해야 합니다. Jython은 파이썬의 표준 라이브러리 일부만 지원하며, 최신 파이썬 버전의 모든 기능을 지원하지 않을 수 있습니다. 반면, ProcessBuilder를 사용하는 방법은 별도의 파이썬 설치가 필요하며 외부 프로세스를 관리해야 한다는 점에서 오버헤드가 발생할 수 있습니다.

 

실제 코드

실제 프로젝트에서 python 웹 크롤러 스크립트를 사용하는 경우 Spring Batch+Quartz 스케줄링을 사용하는 경우가 많습니다. 아래는 Python Script을 실행하는 Tasklet 형태의 ProcessBuilder 코드 입니다.

코드는 kotlin으로 작성되어 있지만 자바 코드와 유사하기에 이해하기에는 어렵지 않습니다.

package kr.co.xxxx.batch.job.exam

import org.slf4j.LoggerFactory
import org.springframework.batch.core.StepContribution
import org.springframework.batch.core.scope.context.ChunkContext
import org.springframework.batch.core.step.tasklet.Tasklet
import org.springframework.batch.repeat.RepeatStatus
import org.springframework.beans.factory.InitializingBean
import org.springframework.beans.factory.annotation.Value
import java.io.BufferedReader
import java.io.InputStreamReader

class ExampleTasklet : Tasklet, InitializingBean {

    @Value("\${crawlers.home}")
    private val crawlersHome: String = ""

    @Throws(Exception::class)
    override fun execute(
        contribution: StepContribution,
        chunkContext: ChunkContext
    ): RepeatStatus {
        val crawler = chunkContext.stepContext
            .jobParameters["crawler"] as String?
        val argsJson = chunkContext.stepContext
            .jobParameters["argsJson"] as String?

        logger.info("Tasklet received parameter: $crawlersHome$crawler $argsJson")

        try {
            val processBuilder = ProcessBuilder("python", "$crawlersHome$crawler", argsJson)
            processBuilder.redirectErrorStream(true)
            val process = processBuilder.start()

            val consoleStream = BufferedReader(InputStreamReader(process.inputStream))
            var consoleLine: String?
            while ((consoleStream.readLine().also { consoleLine = it }) != null) {
                logger.info(consoleLine)
            }
            val exitCode = process.waitFor()
            logger.info("Python script exited with code {}",exitCode)
        } catch (e: java.lang.Exception) {
            logger.error(e.message,e)
        }
        return RepeatStatus.FINISHED
    }

    @Throws(Exception::class)
    override fun afterPropertiesSet() = Unit

    companion object {
        private val logger = LoggerFactory.getLogger(ExampleTasklet::class.java)
    }
}

 

crawlersHome은 파이썬 스크립트 들이 모여있는 디렉토리로 Spring Boot의 application.properties에서 관리되고 있습니다. crawler 파이썬 스크립트 이름으로 스케줄러가 실행되는 시점에 실행되어야할 파이썬 스크립트를 파라미터로 전달해줍니다. argsJson 실행되는 파이썬 스크립트에 전달할 파라미터 입니다. 

 

아래는  스케줄러의  일부 코드를 예시로 보여주고 있습니다. 

package kr.co.xxx.batch.quartz.scheduler

import kr.co.xxxx.batch.job.exam.ExampleQuartzJob
import org.quartz.*
import org.springframework.stereotype.Component

@Component
class ExampleJobScheduler : AbstractJobScheduler() {

    override fun jobDetail(): JobDetail? {
        val jobDataMap = JobDataMap()
        //파이썬 스크립트 이름
        jobDataMap.put("crawler", "crawler_first.py")
        //스크립트에 전달할 파라미터 Json 형태
        jobDataMap.put("argsJson", "{\\\"name\\\":\\\"example\\\"}")

        return JobBuilder.newJob(ExampleQuartzJob::class.java)
            .withIdentity(jobName)
            .setJobData(jobDataMap)
            .storeDurably()
            .build()
    }

    override fun jobTrigger(): Trigger? {
        val scheduleBuilder = SimpleScheduleBuilder
            .simpleSchedule()
            .withIntervalInSeconds(10) // 10초마다 실행
            .repeatForever()
        return TriggerBuilder.newTrigger()
            .forJob(jobDetail())
            .withIdentity(triggerName)
            .withSchedule(scheduleBuilder)
            .build()
    }

    override val jobName: String
        get() = "exampleJob"
    override val triggerName: String
        get() = "exampleTrigger"

    override fun setIsUseTrigger() {
        isUse = false
    }
}

 

 

728x90

'Kotlin for Beginners' 카테고리의 다른 글

JPA Entity을 kotlin으로 개발할때 가이드  (0) 2023.06.09
@JvmStatic에 대해서  (0) 2023.06.09
자바에서 코틀린으로 변환 가이드  (0) 2023.06.09
Kotlin과 다른 언어 비교  (0) 2023.06.02
MyBatis 연동하기  (0) 2023.06.02
Comments