Python을 사용한 R 제어/Scheduler

미완성의 신
8 min readNov 18, 2019

--

목차

Daily Report Project — 기획

글을 쓰기에 앞서

이번글에는 두가지에 초점을 두고 있다.
1. Python으로 하는 스케쥴링
2. Python으로 R 스크립트를 실행하기
1번과 2번은 이번 daily_report에서 동시에 존재하지만 굳이 나눈 이유는 2번 때문인데 python에서 R을 제어 하면서 꽤나 편리한 면이 있기 때문이다. 그럼 이제부터 하나씩 보도록 하자.

1. Python으로 하는 스케쥴링

매일같이 R 프로그램을 돌리고 싶다. R을 막 배울때는 한줄씩 실행하면서 결과를 내곤 했는데, R 스크립트 전체를 한번에 실행하는 방법을 알게 되었다. 터미널에서 다음과 같이 치면 되는데,

Rscirpt test.R

그렇다면 이 test.R 파일을 매일같이 돌아가게 하는 방법은 무엇이 있을까? 하다가 알게 된것이 crontab였다. crontab는 리눅스에서 사용하는 개념인데, 이는 문제가 있더라.

어떤 문제가 있을까? 다음 을 보자.

무엇을 의미하는가? 다음 그림을 우선 보도록 하자.

a1~ a141개. 즉 141개의 프로그램을 돌리고 있다고 가정을 해보자. 이 141개는 단 한명이 아닌 100명이서 각각 담당 하고 있다고 가정을 해보자. 이때, 유지보수에 대해 이야기를 해야 하는데, Crontab를 사용 할 경우 각각 담당자들이 하나의 crontab들어가서 일일이 찾아서 수정을 해주어야 한다. 이때 b1이라는 사람이 a56을 담당 하고 있는데, 저 많은 줄에서 찾다가 실수로 a55를 지우면? a55를 담당 했던 b2라는 사람은 영문도 모르고 어느날 갑자기 프로그램이 멈춰버린 곤란한 상황을 겪을 수 있다.

반면에, 파이썬 스케쥴러를 사용 할 경우에는 이런 문제를 예방 할 수 있다. 각각의 개발자들은 각자가 만든 python 파일을 알 고 있다. (물론 a1,a2, …, a141 이라는 가독성이 좋지 않게 표현을 했지만.) 그럼 그 개발자 들은 알아서 각자의 파일을 꺼낸뒤 코드를 보고 수정을 하면 된다. (단지 그 뿐)

이러한 이유로

crontab이 아닌 파이썬으로 한 스케쥴러를 작성해보자. 우선 schedule 모듈을 설치 하도록 하자. 설치 코드는 다음과 같다.

pip3 install schedule

그럼 이제 파이썬 파일을 하나 만들도록 하자. 환경은 리눅스(우분투)로 진행한다. touch schedule.py 라는 코드로 schedule.py 를 만드는 과정이다.

touch schedule.py

이후, vi schedule.py라는 코드를 쓸 건데 이는 schedule.py를 직접적으로 수정 하겠다는 의미이다.

vi schedule.py

이렇게 되면 새로운 창이 뜨는데 리눅스에서는 ‘a’ 를 입력하여 수정을 할 수 있게 된다. a를 누르고 다음과 같은 코드를 작성 하자.

import schedule
import time
def job():
print(“I’m working…”)
# 10초마다
schedule.every(10).seconds.do(job)
# 10분에 한번씩
#schedule.every(1).minutes.do(job)
# 1hour
#schedule.every().hour.do(job)
# do 10:30 everyday
#schedule.every().day.at(“10:30”).do(job)
# monday
#schedule.every().monday.do(job)
# monday 10:13
#schedule.every().wednesday.at(“13:15”).do(job)
while True:
schedule.run_pending()
time.sleep(1)

schedule, time 모듈을 불러와서 10초마다 im working.. 를 print 하도록 해놓았다. 이제 esc버튼 :버튼을 눌러서 wq를 적고 엔터. wq는 덮어쓰기를 의미한다.(write quit) 이제 이 파일을 실행 해볼껀데 파이썬의 스크립트 실행 코드는 다음과 같다.

python3 schedule.py

파이썬은 버전2와 3으로 나뉘는데, 우리는 3버전으로 사용한다.

10초마다 I’m working를 print 하는 모습.

건드리지 않으면 계속 실행이 되는데, 이때 ctrl + c 버튼으로 종료 하자.

이렇게 python의 schedule는 마무리 되었다. 물론 이 schedule도 중요하지만 R을 하는 입장에서 가장 소개 하고 싶은 부분은 2번.

2. Python으로 R 스크립트를 실행하기

파이썬에서 R스크립트를 실행 해보자. 기존에 Rscript test.R 이라는 R 스크립트 실행 코드를 소개 했는데, 이를 파이썬에서 실행 해보겠다는 뜻. 역시 touch test.py 로 python 파일을 생성하고 vi test.py로 수정을 하도록 하자. 그리고 다음의 코드를 작성한다.

import os os.system(“/usr/bin/Rscript /home/owen/test.R”)

왜? Rscript test.R 이 아니라 /usr/bin/Rscirpt /home/owen/test.R인가?

이때부터는 절대경로라는걸 사용한다. 절대 경로라는건 쉽게 말해서

우리 옆집 철수네 라는 표현을 사용하는게 아닐, xx시 xx구 xx동 xx아파트 xx동 xx호 라는 철수가 살고 있는 정확한 집 주소를 알고자 하는것.

Rscript함수의 절대 경로를, test.R의 절대 경로를 사용해서 실행을 해야 한다. 그럼 이 방법의 장점이 무엇일까? R 에서 처리 할수있는 데이터의 한계가 있을 것이다. 이를 약 1억건 이라고 해보자. 1억건의 데이터를 한번에 처리를 하려다 보니 매번 메모리 문제로 시스템에 과부하가 생겨 멈추게 된다.

그럼?

천만건은 돌아가니 천만건을 나눠서 10번 돌리자! 다만.. 사람이 직접 10번 하는게 아니라 python안에서 제어를 해서 돌리도록 하자.

이럴경우 메모리 문제를 겪지 않고도 무난하게 1억건의 데이터를 처리 할 수 있다. 본격적으로 코드를 보자.

Tips

많은 양의 데이터를 처리 하다 보면 즉, 아무리 python에서 천만건씩 10번 돌리더라도 끊어 질 수 있다. 이때 사용하는 방법이 백엔드에서 돌리는것. 기존에 python3 test.py 를 실행하는거라면 백엔드에서 실행할때는 다음의 코드를 사용한다.

nohup python3 test.py &

처음에 nohup, 끝에 &를 써주면 백엔드에서 돌아가는데, 이는 안쪽에서 돌아가기에 겉으로 보이지가 않는다. 이에 앞서 설명 했던 ctrl + c 를 할수가 없는데, nohup로 생성시 고유의 번호가 주어진다.

여기서 이 20137은 이 프로그램이 돌아가는 고유의 번호라고 해석을 하면 되는데, 이를 종료 하기 위해서는 kill -9 20137을 하면 된다.

또, 5일이 걸릴 거 같은 작업을 실행 했을때 현재 돌아가고 있는지 확인 하기 위해서는 다음의 코드를 사용한다.

ps -ef | grep python3

이러면 해당 프로그램이 백엔드에서 돌아가고 있는지 아닌지를 알 수 있다.

이 방법은 또 어떻게 응용을 할 수 있을까?

  • R에서 외부 변수를 파라미터로 받아와 사용 할 수 가 있다.
  • 또 파이썬에서 for문 등등을 사용해 외부 변수를 만들어 주고 이를 R을 실행하는데에 넣어 줄 수 있다.

이는 언젠가 블로그에 작성 하도록 하겠다. 주제와 벗어나기때문.

Daily_report에서의 관점

지금까지 1번과 2번에 대해서 알아 두었으니 daily_report를 위한 R을 실행 해보도록 하자.(참고: R에서 Rmd를 호출하자) schedule.py라는 스크립트를 만들었고 이 안에 들어가는 코드는 다음과 같다. 매일 06시에 daily_report.R 을 실행 하도록 짜준다.

import schedule
import time
import os
os.system(“/usr/bin/Rscript /home/owen/daily_report_test/daily_report.R”)def job():
os.system(“/usr/bin/Rscript /home/owen/daily_report_test/daily_report.R”)
# do 10:30 everyday
schedule.every().day.at(“06:00”).do(job)
while True:
schedule.run_pending()
time.sleep(1)

최종적으로 nohup python3 schedule.py & 라고 schedule.py를 백엔드에서 돌림으로써 매일 6시에 이 파이썬 파일은 돌아가고 파이썬 파일에서 R을 실행하게 된다.

총평

전하고자 하는 말이 너무 많았다. 쓰다 보니 설명을 해야 할 것들이 넘쳐 나는데, 개인적으로 블로그에 드래그를 많이 하게 하는걸 좋아 하지 않아 불편한 감이 너무도 많이 있다.

--

--

미완성의 신

우리 인간은 미완성의 신들이다. 뛰어난 데이터 과학자를 꿈꾸는. 책을 좋아하는. 그런 사람입니다.