pyenv-virtualenv를 이용해 가상환경에서 만든 파이썬을 crontab에 추가해 실행하는 방법을 알아보자


환경

  • Linux
  • pyenv
  • pyenv-virtualenv


글 배경

배경

  • 파이썬 버전에 따른 의존성을 없애기 위해 pyenvpyenv-virtualenv와 같은 가상환경을 사용하는데 가상환경에서 만든 코드를 crontab에서 실행할 상황이 생겼다.
  • crontab뿐만 아니라 systemd에 서비스를 등록할 때나 쉘스크립트를 작성해서 실행할 때도 적용 가능하다.


사전 지식

파이썬 모듈과 경로

  • 결국 파이썬을 실행할 때 중요한 부분은 여러가지가 있겠지만 모듈이 저장된 위치와 사용할 파이썬이 어디에 위치하냐가 중요하다.


sys.path

  • sys.path: 파이썬 모듈을 사용할 때 참조하는 경로를 저장하고 있는 리스트입니다.
  • import를 사용해서 모듈을 가져올 때 참조하게 됩니다.
>>> import sys
>>> sys.path
['', '/home/twpower/.pyenv/versions/3.6.2/lib/python36.zip', '/home/twpower/.pyenv/versions/3.6.2/lib/python3.6', '/home/twpower/.pyenv/versions/3.6.2/lib/python3.6/lib-dynload', '/home/twpower/.pyenv/versions/jupyter-notebook/lib/python3.6/site-packages']


pyenv versions

  • pyenv를 통해 설치된 여러 파이썬 버전들을 볼 수 있는 명령어
  • pyenv-virtualenv를 통해 만든 가상환경들도 목록에 나온다.
$ pyenv versions
* system (set by /home/twpower/.pyenv/version)
  3.5.2
  3.5.3
  3.6.1
  3.6.2
  3.6.2/envs/jupyter-notebook
  3.6.2/envs/test
  jupyter-notebook
  test


pyenv path

  • 위에 나온 pyenv versions에 해당하는 파이썬 및 모듈들은 $(pyenv root)/versions의 경로에 있다.
$ ls /home/twpower/.pyenv/versions/
3.5.2  3.5.3  3.6.1  3.6.2  jupyter-notebook  test


적용 방법

방법1 - 사용할 가상환경의 파이썬을 직접 선택

  • pyenv-virtualenv는 가상환경마다 사용하는 파이썬이 다릅니다. 그렇기에 사용하는 경로도 다르고 그에 따른 sys.path도 다릅니다.
  • pyenv-virtualenv에서 사용하는 파이썬을 직접 이용해 .py파일을 실행하면 됩니다.
  • 경로: [pyenv root]/versions/[virtualenv name]/bin/[python version]

crontab

30 20 * * * /home/twpower/.pyenv/versions/jupyter-notebook/bin/python3.6 /home/twpower/test.py


방법2 - 스크립트에서 “pyenv activate”를 사용

  • 쉘 스크립트로 파일을 만들고 해당 스크립트에 pyenv activate를 통해 가상환경을 만들어주고 파이썬 코드를 실행합니다.

test.sh

#!/bin/bash

source /home/twpower/.bash_profile
source /home/twpower/.bashrc

pyenv activate jupyter-notebook
python /home/twpower/test.py

crontab

30 20 * * * /home/twpower/test.sh


참고자료

Add python file which runs in pyenv-virtualenv to crontab and run it.


Environment and Prerequisite

  • Linux
  • pyenv
  • pyenv-virtualenv


Post Background

Background

  • To isolate dependency in python versions, people use pyenv and pyenv-virtualenv. By using those softwares we can make virtual environment which can run python code file. I encounter run python code file in crontab which runs in virtual environment.
  • It can be used in not only crontab but also systemd’s service and shell script.


Prior knowledge

Python Module and Path

  • When running python code file, there are many important things to care. However this post focus on python module path and which python you use.


sys.path

  • sys.path: A list of strings that specifies the search path for modules.
  • Refer sys.path when load python module using import.
>>> import sys
>>> sys.path
['', '/home/twpower/.pyenv/versions/3.6.2/lib/python36.zip', '/home/twpower/.pyenv/versions/3.6.2/lib/python3.6', '/home/twpower/.pyenv/versions/3.6.2/lib/python3.6/lib-dynload', '/home/twpower/.pyenv/versions/jupyter-notebook/lib/python3.6/site-packages']


pyenv versions

  • Show number of python versions which installed by pyenv
  • Also includes pyenv-virtualenv’s virtual environment.
$ pyenv versions
* system (set by /home/twpower/.pyenv/version)
  3.5.2
  3.5.3
  3.6.1
  3.6.2
  3.6.2/envs/jupyter-notebook
  3.6.2/envs/test
  jupyter-notebook
  test


pyenv path

  • pyenv versions python and modules are located in $(pyenv root)/versions path.
$ ls /home/twpower/.pyenv/versions/
3.5.2  3.5.3  3.6.1  3.6.2  jupyter-notebook  test


How To Apply

Method1 - Use virtual environment’s python directly

  • Each pyenv-virtualenv has its own python. So its python path is different and also sys.path is different.
  • Use python code file directly which is in pyenv-virtualenv.
  • Path: [pyenv root]/versions/[virtualenv name]/bin/[python version]

crontab

30 20 * * * /home/twpower/.pyenv/versions/jupyter-notebook/bin/python3.6 /home/twpower/test.py


Method2 - Use “pyenv activate” in script

  • Add pyenv activate to make virtual environment in shell script and run python code.

test.sh

#!/bin/bash

source /home/twpower/.bash_profile
source /home/twpower/.bashrc

pyenv activate jupyter-notebook
python /home/twpower/test.py

crontab

30 20 * * * /home/twpower/test.sh


Reference

구조 분해 할당을 통해서 값을 받아보자.


환경

  • Javascript


구조 분해 할당

정의

  • 구조 분해 할당(Destructuring assignment): 배열이나 객체에서 원소나 속성을 해체하여 그 값들을 각각의 변수에 담을 수 있도록 하는 구문
  • 다양한 예제들은 아래 ‘참고자료’에 있는 링크에 많이 있다.


간단한 예제

배열 구조 분해

let arr = [1, 2, 3, 4, 5];
let [a, b, ...c] = arr;

console.log(arr);
console.log(a);
console.log(b);
console.log(c);
[ 1, 2, 3, 4, 5 ]
1
2
[ 3, 4, 5 ]

객체 구조 분해

let object = {
  a: 1,
  b: "test",
  c: [1, 2],
  d: { name: "test", age: 28 },
};

// Key must be same
let { a, b, c, d } = object;

/* Assign to different variable name example
let { a: e, b: f, c: g, d: h } = object;
*/

console.log(a);
console.log(b);
console.log(c);
console.log(d);
1
test
[ 1, 2 ]
{ name: 'test', age: 28 }


사용

  • 이러한 구조 분해 할당(Destructuring assignment)을 사용하면 함수에서 반환된 값을 여러개로 받을 수 있다. 이는 정확하게는 객체나 배열을 반환하고 이를 구조 분해 할당을 통해 받는거다.

배열 반환 예제

function test() {
  return [1, 2, 3, 4, 5];
}

let [a, b, ...c] = test();

console.log(a);
console.log(b);
console.log(c);
1
2
[ 3, 4, 5 ]

객체 반환 예제

function test() {
  let object = {
    a: 1,
    b: "test",
    c: [1, 2],
    d: { name: "test", age: 28 },
  };

  return object;
}

let { a, b, c, d } = test();

console.log(a);
console.log(b);
console.log(c);
console.log(d);
1
test
[ 1, 2 ]
{ name: 'test', age: 28 }


참고자료

Get values using destructuring assignment.


Environment and Prerequisite

  • Javascript


Destructuring Assignment

Definition

  • Destructuring assignment: It is an syntax which can unpack values from elements of array or properties in object.
  • There are many examples on link in below ‘Reference’


Simple Examples

Array Destructuring

let arr = [1, 2, 3, 4, 5];
let [a, b, ...c] = arr;

console.log(arr);
console.log(a);
console.log(b);
console.log(c);
[ 1, 2, 3, 4, 5 ]
1
2
[ 3, 4, 5 ]

Object Destructuring

let object = {
  a: 1,
  b: "test",
  c: [1, 2],
  d: { name: "test", age: 28 },
};

// Key must be same
let { a, b, c, d } = object;

/* Assign to different variable name example
let { a: e, b: f, c: g, d: h } = object;
*/

console.log(a);
console.log(b);
console.log(c);
console.log(d);
1
test
[ 1, 2 ]
{ name: 'test', age: 28 }


Usage

  • By using this destructuring assignment, we can return multi values from function. Technically, its function return object or array and receives its values in caller using destructuring assignment.

Array Destructuring Example

function test() {
  return [1, 2, 3, 4, 5];
}

let [a, b, ...c] = test();

console.log(a);
console.log(b);
console.log(c);
1
2
[ 3, 4, 5 ]

Object Destructuring Example

function test() {
  let object = {
    a: 1,
    b: "test",
    c: [1, 2],
    d: { name: "test", age: 28 },
  };

  return object;
}

let { a, b, c, d } = test();

console.log(a);
console.log(b);
console.log(c);
console.log(d);
1
test
[ 1, 2 ]
{ name: 'test', age: 28 }


Reference

Jekyll Liquid 템플릿에서 배열을 만들고 원소를 추가하는 방법을 알아보자


환경

  • Linux
  • Jekyll


Jekyll 배열 생성 및 추가

생성

  • split 필터 사용
  • 문자열을 ,로 구분해 배열로 만드는 필터로 문자열이 없기 때문에 빈 배열을 만듭니다.
{% assign ARRAY_NAME = "" | split: ',' %}


추가

  • push 사용해 배열에 추가하고 추가한 배열을 변수에 다시 할당합니다.
  • push를 하면 현재 배열에 추가된채로 저장되는게 아니기 때문에 새로 할당해야 합니다.
{% assign ARRAY_NAME = ARRAY_NAME | push: ELEMENT %}


예제

  • 아래는 블로그에서 특정 collections를 가져와서 새로 배열을 만드는 예시
  • opensource-contributions: 배열
  • post: 원소
{% assign opensource-contributions = "" | split: ',' %}
{% for post in site.opensource-contributions %}
  {% if post.post_id != page.post_id %}
     {% assign opensource-contributions = opensource-contributions | push: post %}
  {% endif %}
{% endfor %}


참고자료